だから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
終了後にパイプが破壊されるので、rsync
stderrに書き込もうとするとパイプが終了するからです。
だから:
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
答え2
両方の親であるスクリプトを書くことは簡単です。両方制御。または2つのチャネル間の通信チャネルの構築。
特定のバックグラウンドジョブを具体的に無視するには、PID($!
最後のバックグラウンドジョブPID)をキャプチャし、wait $pid
そのジョブが完了するのを待ちます。
答え3
-f
ssh
問題を解決するにはフラグを指定してください。テスト対象:
#!/bin/sh -e
echo $$_script__begin
( echo sleeping; sleep 2; echo slept )&
echo $$_script__end
を使用して実行すると、表示されるssh localhost ./script
まで待ちます。slept
この-f
フラグを使用すると、コマンドが返された後に終了し、echo $$_script__end
後でslept
バックグラウンドに表示されます。ssh
答え4
これを試してみてください。$!
最後に実行されたバックグラウンドパイプ/プロセスのプロセスIDを含むデフォルトのシェル変数。
command1 &
lpid1=$!
command2 &
lpid2=$!
command3 &
lpid=$!
wait $lpid1 # waits for only the process with PID lpid1 to complete.
スクリプトに基づいてexport
変数などを使用してこれを利用する必要があります。