由脚本启动的循环中进程的 PID

由脚本启动的循环中进程的 PID

我通过 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知道其编号(listener1listener2),以便它可以使用具有正确编号的文件。


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 攻击。

相关内容