web-dev-qa-db-ja.com

サブシェルバ​​ックグラウンドプロセスpidを変数に割り当てます

現在、サブシェル内でバックグラウンドプロセスを開始していますが、そのpid番号をサブシェルスコープ外の変数に割り当てるにはどうすればよいですか?
さまざまな方法を試しましたが、MYPIDは常に0に設定されたままです。

MYPID = 0;
({ sleep 2 & }; $MYPID=$!)
({ sleep 2 & }; echo $!) > $MYPID

値を返す唯一の方法は次のとおりです。

$MYPID=$({ sleep 2 & }; echo $!)

ただし、これによりバックグラウンドプロセス命令が破棄され、2秒後にのみ結果が返されます。

5
zanona

bashは、非対話型の場合、ジョブのステータスを出力しないでください。

それが実際にインタラクティブなbashの場合は、次のことができます。

_{ pid=$(sleep 20 >&3 3>&- & echo "$!"); } 3>&1
_

sleepのstdoutは、_$pid_変数にフィードするパイプではなく、以前の場所に移動する必要があります。したがって、outer stdoutをファイル記述子3(_3>&1_)に保存し、コマンド置換内でsleep用に復元します。したがって、_$pid_をフィードするパイプに開いているファイル記述子が残っていないため、pid=$(...)echoが終了するとすぐに戻ります。

ただし、サブシェル(ここではコマンド置換)から開始されるため、そのsleepは別のプロセスグループでは実行されないことに注意してください。したがって、たとえば端末へのI/Oに関しては、_sleep 20 &_を実行することと同じではありません。

おそらく、スポーンをサポートするシェルを使用する方が良いでしょうdisownedzshのようなバックグラウンドジョブを実行できます。

_sleep 20 &! pid=$!
_

bashを使用すると、次のように概算できます。

_{ sleep 20 2>&3 3>&- & } 3>&2 2> /dev/null; pid=$!; disown "$pid"
_

bashは_[1] 21578_をstderrに出力します。繰り返しになりますが、/ dev/nullにリダイレクトする前にstderrを保存し、sleepコマンド用に復元します。このように、_[1] 21578_は_/dev/null_に移動しますが、sleepのstderrは通常どおりに移動します。

とにかくすべてを/ dev/nullにリダイレクトする場合は、次のようにするだけです。

_{ apt-get update & } > /dev/null 2>&1; pid=$!; disown "$pid"
_

Stdoutのみをリダイレクトするには:

_{ apt-get-update 2>&3 3>&- & } 3>&2 > /dev/null 2>&1; pid=$!; disown "$pid"
_
8

2行目が機能しない

({ sleep 2 & }; $MYPID=$!)

( ... )サブシェルをフォークすると、MYPIDが設定され、サブシェルが終了すると、その値が失われます。

3行目も機能しませんでした

({ sleep 2 & }; echo $!) > $MYPID

$をエコーするだけです!ローカルディレクトリの0という名前のファイルに。

私が提供できる唯一の答えは、一時ファイルを介することです(varはプッシュバックできないため)

 ( { sleep 100 & } ; echo $! > u ) > /dev/null &> /dev/null
 MYPID=$(<u)

uは任意のファイルに置き換えることができます。

2
Archemar