У меня есть несколько процессов, запущенных через bash-скрипт, которые прослушивают и воспроизводят через netcat аудиопотоки, поступающие на отдельные порты:
#!/bin/bash
# listener.sh
while :
do
nc -l 900$1 | aplay -
sleep 1
done
exit 0
Этот скрипт запускается в другом скрипте с аргументами для определения уникальных портов, например:
#!/bin/bash
# startlisterners.sh
if [ ! -f /tmp/listener1.pid ]; then
nohup listener.sh 1 &
echo $! > /tmp/listener1.pid
fi
if [ ! -f /tmp/listener2.pid ]; then
nohup listener.sh 2 &
echo $! > /tmp/listener2.pid
fi
..... etc.
exit 0
Мне периодически необходимо иметь возможность выборочно убивать экземпляры «aplay» в подскриптах, при этом сами подскрипты должны работать.
Как получить доступ к индивидуальным PID каждого процесса aplay?
решение1
Вместо
nc -l 900$1 | aplay -
sleep 1
бегать
nc -l "900$1" | aplay - &
# here you can use $!
wait
sleep 1
Теперь, когда он читает, # here you can use $!
вы можете, например, записать $!
в предопределенный файл. Этот подход может потребовать listener.sh
знать его номер ( listener1
и listener2
т. д.), чтобы он мог использовать файл с правильным номером.
Другой способ — определить ловушку while
до listener.sh
:
trap 'kill "$!"' SIGUSR2
При такой реализации, если вы отправите SIGUSR2
( kill -s SIGUSR2 …
) процессу listener.sh
, то он будет иметь kill
свой собственный aplay
. Вы уже знаете PID ваших слушателей благодаря /tmp/listener*.pid
файлам.
Имейте в виду, чторуководствоговорит:
Если Bash ожидает завершения команды и получает сигнал, для которого установлена ловушка, ловушка не будет выполнена, пока команда не завершится. Когда Bash ожидает асинхронную команду через встроенную функцию
wait
, получение сигнала, для которого установлена ловушка, приведет кwait
немедленному возврату встроенной функции со статусом выхода больше128
, сразу после чего выполняется ловушка.
Это значит, что вам следует запустить его aplay
в фоновом режиме wait
(как указано выше).
Я могу только предположить, что вы запускаете несколько слушателей, чтобы иметь возможность обслуживать несколько клиентов (все еще максимум одного клиента на порт в любой момент времени). Затем вам иногда нужно убивать aplay
, например, когда клиент тихо исчезает и nc
не получает уведомления.
Может быть, этовесьподход можно заменить одним socat
:
socat TCP-LISTEN:9001,fork EXEC:'aplay -'
Благодаря fork
этому он может обслуживать несколько клиентов на одном порту. Используйте -T
опцию (см. man 1 socat
) для завершения устаревших соединений. Даже без -T
них следуеттайм-аут в конце концовВ любом случае. Однако решение уязвимо для DOS-атаки.