スクリプトによって開始されたループ内のプロセスの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別の方法としては、の前にトラップを定義することですlistener.sh

trap 'kill "$!"' SIGUSR2

これを実装すると、プロセスにSIGUSR2( )を送信すると、そのプロセス独自のが送信されます。ファイルのおかげで、リスナーの PID はすでにわかっています。kill -s SIGUSR2 …listener.shkillaplay/tmp/listener*.pid

気にするなマニュアル言う:

Bash がコマンドの完了を待機しているときに、トラップが設定されているシグナルを受信した場合、コマンドが完了するまでトラップは実行されません。Bash が組み込みコマンドを介して非同期コマンドを待機している場合wait、トラップが設定されているシグナルを受信すると、wait組み込みコマンドは より大きい終了ステータスで直ちに戻り128、その直後にトラップが実行されます。

つまり、aplayバックグラウンドで実行する必要がありますwait(上記のように)。


複数のクライアントにサービスを提供できるようにするために、複数のリスナーを実行しているとしか思えません (ただし、特定の時点ではポートごとに最大 1 つのクライアントです)。その後、クライアントが静かに消えて通知されないaplay場合など、時々 kill を実行する必要があります。nc

たぶんこれは全体アプローチは単一の に置き換えることができますsocat:

socat TCP-LISTEN:9001,fork EXEC:'aplay -'

fork同じポートで複数のクライアントにサービスを提供できます。古い接続を終了するには、-Tオプション(を参照)を使用します。man 1 socat-T最終的にタイムアウトとにかく。ただし、このソリューションは DOS 攻撃に対して脆弱です。

関連情報