Tenho vários processos iniciados por meio de um script bash, ouvindo e reproduzindo, via netcat, fluxos de áudio que chegam em portas separadas:
#!/bin/bash
# listener.sh
while :
do
nc -l 900$1 | aplay -
sleep 1
done
exit 0
Este script é lançado em outro script com argumentos para definir portas exclusivas. por exemplo.
#!/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
Preciso, periodicamente, ser capaz de eliminar seletivamente instâncias de "aplay" nos subscritos, enquanto mantenho os próprios subscritos em execução.
Como posso acessar os PIDs individuais de cada processo aplay?
Responder1
Em vez de
nc -l 900$1 | aplay -
sleep 1
correr
nc -l "900$1" | aplay - &
# here you can use $!
wait
sleep 1
Agora, onde ele lê, # here you can use $!
você pode, por exemplo, gravar $!
em um arquivo predefinido. Essa abordagem pode exigir listener.sh
o conhecimento de seu número ( listener1
, listener2
etc.) para poder usar um arquivo com o número correto.
Outra maneira é definir uma armadilha antes while
em listener.sh
:
trap 'kill "$!"' SIGUSR2
Com isso implementado, se você enviar SIGUSR2
( kill -s SIGUSR2 …
) para um listener.sh
processo, ele será kill
seu aplay
. Você já conhece os PIDs dos seus ouvintes graças aos /tmp/listener*.pid
arquivos.
Cuidado com o queo manualdiz:
Se o Bash estiver aguardando a conclusão de um comando e receber um sinal para o qual uma armadilha foi definida, a armadilha não será executada até que o comando seja concluído. Quando o Bash está aguardando um comando assíncrono através do
wait
builtin, a recepção de um sinal para o qual uma armadilha foi definida fará com que owait
builtin retorne imediatamente com um status de saída maior que128
, imediatamente após o qual a armadilha é executada.
Isso significa que você deve executar aplay
em segundo plano e wait
para isso (como acima).
Só posso supor que você execute vários ouvintes para poder atender vários clientes (ainda no máximo um cliente por porta a qualquer momento). Então você ocasionalmente precisa kill aplay
, por exemplo, quando um cliente desaparece silenciosamente e nc
não é notificado.
Talvez istointeiroabordagem pode ser substituída por uma única socat
:
socat TCP-LISTEN:9001,fork EXEC:'aplay -'
Graças a fork
ele pode atender vários clientes na mesma porta. Use a -T
opção (consulte man 1 socat
) para encerrar conexões obsoletas. Mesmo sem -T
eles deveriamtempo limite eventualmentede qualquer forma. A solução é vulnerável a um ataque DOS.