Instead of
nc -l 900$1 | aplay -
sleep 1
run
nc -l "900$1" | aplay - &
# here you can use $!
wait
sleep 1
Now where it reads # here you can use $!
you can e.g. write $!
to a predefined file. This approach may require listener.sh
to know its number (listener1
, listener2
etc.) so it can use a file with the right number.
Another way is to define a trap before while
in listener.sh
:
trap 'kill "$!"' SIGUSR2
With this implemented, if you send SIGUSR2
(kill -s SIGUSR2 …
) to a listener.sh
process then it will kill
its own aplay
. You already know the PIDs of your listeners thanks to /tmp/listener*.pid
files.
Mind what the manual says:
If Bash is waiting for a command to complete and receives a signal for which a trap has been set, the trap will not be executed until the command completes. When Bash is waiting for an asynchronous command via the wait
builtin, the reception of a signal for which a trap has been set will cause the wait
builtin to return immediately with an exit status greater than 128
, immediately after which the trap is executed.
This means you should run aplay
in the background and wait
for it (like above).
I can only guess you run multiple listeners to be able to serve multiple clients (still at most one client per port at any given time). Then you occasionally need to kill aplay
, e.g. when a client silently disappears and nc
is not notified.
Maybe this entire approach can be replaced by a single socat
:
socat TCP-LISTEN:9001,fork EXEC:'aplay -'
Thanks to fork
it can serve multiple clients on the same port. Use the -T
option (see man 1 socat
) to terminate stale connections. Even without -T
they should timeout eventually anyway. The solution is vulnerable to a DOS attack though.