(bash) スクリプト A はスクリプト B を待ちますが、子プロセスは待ちません。

(bash) スクリプト A はスクリプト B を待ちますが、子プロセスは待ちません。

だからscriptAがあり、その役割は次のとおりです。

ssh server1 -- scriptB &
ssh server2 -- scriptB &
ssh server3 -- scriptB &
wait
otherstuffhappens

ScriptBの機能は次のとおりです。

rsync -av /important/stuff/. remoteserver:/remote/dir/.
rsync -av /not/so/important/stuff/. remoteserver:/remote/dir/. &
exit

私が望む結果は、scriptAが続行する前にscriptBのすべてのインスタンスが完了するのを待つことです。現在はそうしていますが、それほど重要ではない項目のバックグラウンドrsyncも待っています。このファイルは大きいので、待ちたくありません。

私はすべて読んだnohup、disown、&の違いいろいろな組み合わせを試してみましたが、目的の結果が得られませんでした。

この時点で私は混乱しています。どんな助けでも大変感謝します!

ベストアンサー1

ここでの問題は、sshdコマンドのstdoutを読み取るパイプのファイルの終わりを待つことです(少なくともテスト中のバージョンでは何らかの理由でstderrの代わりに)。そしてバックグラウンドジョブはパイプラインのfdを継承します。

したがって、この問題を解決するには、バックグラウンド コマンドの出力を一部のファイルにrsyncリダイレクトしたり、/dev/null気にしないようにしてください。また、stderrをリダイレクトする必要があります。 sshdがそのパイプを待たなくてもsshd終了後にパイプが破壊されるので、rsyncstderrに書き込もうとするとパイプが終了するからです。

だから:

rsync ... > /dev/null 2>&1 &

比較する:

$ time ssh localhost 'sleep 2 &'
ssh localhost 'sleep 2 &'  0.05s user 0.00s system 2% cpu 2.365 total
$ time ssh localhost 'sleep 2 > /dev/null &'
ssh localhost 'sleep 2 > /dev/null &'  0.04s user 0.00s system 12% cpu 0.349 total

そして:

$ ssh localhost '(sleep 1; ls /x; echo "$?" > out) > /dev/null &'; sleep 2; cat out
141  # ls by killed with SIGPIPE upon writing the error message
$ ssh localhost '(sleep 1; ls /x; echo "$?" > out) > /dev/null 2>&1 &'; sleep 2; cat out
2    # ls exited normally after writing the error on /dev/null instead
     # of a broken pipe

おすすめ記事