由腳本啟動的循環中進程的 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 攻擊。

相關內容