![由脚本启动的循环中进程的 PID](https://linux22.com/image/170824/%E7%94%B1%E8%84%9A%E6%9C%AC%E5%90%AF%E5%8A%A8%E7%9A%84%E5%BE%AA%E7%8E%AF%E4%B8%AD%E8%BF%9B%E7%A8%8B%E7%9A%84%20PID.png)
我通过 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”实例,同时保持下标本身运行。
如何访问每个 aplay 进程的单独 PID?
答案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
另一种方法是在 in之前定义陷阱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 攻击。