我透過 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 攻擊。