このようにしてプロセスのPIDを開始するにはどうすればよいですか?

このようにしてプロセスのPIDを開始するにはどうすればよいですか?
#!/bin/bash

mkfifo /var/run/out
while true
do
    cat /var/run/out | nc -l 8080 > >(
        while read line
        do
            do some stuff
        done
    )
done

nc合計のpidをどのように取得できますかcat? $!を使用すると機能しません。 pidファイルに書きたいです。

答え1

必要なものを実行するよりエレガントな方法があるかもしれませんが、次のように動作します。

do
    (cat /var/run/out& echo $! > cat_pid; wait) |
                            (nc -l 8080 <&0 & echo $! > nc_pid; wait) > >(

(読みやすくするために、末尾を別々の行に分割しました|)まで待つのです。 (実際には、コマンドを前景に戻します。)スコット <&0非同期プロセスがスクリプトから正しい標準入力を読み取るようにするためのヒントです。

しかし、なぜ「猫」を使うのですか??そして> >(…)単純パイプの代わりになぜ使用しましたか?

これは次のように単純化できます。

本当ではありますが
する
    (nc -l 8080 < /var/run/out & echo $! > nc_pid; 待機) |
                行を読むとき
                する
                    何かをしなさい
                完璧
完璧

nc直接読み、/var/run/outプロセスの置き換えの代わりに単純なパイプを使用してください。

答え2

私が考えることができる最も簡単な方法は、プロセスを開始する前にpidを取得することです。

たとえば(Bashから):

pidfile() { (
    echo $BASHPID > "$1"
    shift
    exec "$@"
) }

mkfifo /var/run/out
while true
do
    pidfile /tmp/cat.pid cat /var/run/out | pidfile /tmp/nc.pid nc -l 8080 > >(
        while read line
        do
            do some stuff
        done
    )
done

pidfileこれにより、現在のPIDを指定されたファイルに書き込み、残りのパラメータを使用して実行する関数が生成されますexec。これexecにより、ファイルを作成したシェルと同じpidでコマンドが実行されます。

サブシェルで実行するためにpidfile()関数全体を括弧で囲みます。()パイプラインにないコマンドを実行する場合、これは非常に重要です。たとえば、

pidfile /tmp/foo some command here

これはpidfile()スクリプトの残りの部分と同じプロセスで実行されるため、呼び出されると実行中execのコマンドはPIDを引き継ぎ、スクリプトは実行されなくなります。

また、上記はbash用に書かれています。$BASHPIDbash 特定の変数です。$$これはサブシェルを使用しても変更されないため、この値は私たちの使用には適していません。

答え3

catまたはPIDを取得できません。nc そのスクリプトからそうでなければバックステージコースそして&。バックグラウンドに含まれていないすべてのプロセスはバックグラウンドに含める必要があります。終わるスクリプトが続く前に。

これBash Wikiプロセス管理記事これらのことを賢明に行う方法について説明します。

関連情報