次のようなbashスクリプトがあります。
##script #!/bin/bash rm data* rm logfile* for i in {1..30} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & done
最初のループの後に別のforループを作成して、別の30に続けたいと思います。たとえば、
##script #!/bin/bash rm data* rm logfile* for i in {1..30} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & for i in {31..60} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & done
新しいセットを開始する前に終了する最初のジョブのセット。しかし、nohup
のため、これらはすべて同時に実行されているようです。
nohup
があります。これは、サーバーにリモートでログインしてそこでジョブを開始してから、bashを閉じるためです。別の解決策はありますか?
コメント
回答
wait
コマンドを使用してこれを実行します。すべての子プロセスIDをキャプチャして具体的に待機するか、スクリプトが作成するバックグラウンドプロセスがそれらだけである場合は、wait
を呼び出すだけです。引数なし。例:
#!/bin/bash # run two processes in the background and wait for them to finish nohup sleep 3 & nohup sleep 10 & echo "This will wait until both are done" date wait date echo "Done"
回答
いくつかのポイント:
-
nohup
の目標が、リモートシェル出口によるワーカープロセスの強制終了を防ぐことである場合は、スクリプト自体で、スクリプトが作成する個々のワーカープロセスではありません。 -
説明されているようにここで、
nohup
は、プロセスがSIGHUPを受信するのを防ぐだけですと端末との相互作用から、しかしそれはシェルとその子プロセスの間の関係を壊しません。 -
上記のポイントのため、、2つの
for
ループ間の単純なwait
により、2番目のfor
最初のfor
によって開始されたすべての子プロセスが終了した後にのみ実行されます。 -
単純な
wait
:現在アクティブなすべての子プロセスが待機され、戻りステータスはゼロです。
-
2番目の
for
を実行する必要がある場合は、最初のエラーがなかった場合のみ次に、各ワーカーPIDを$!
で保存し、それらすべてをwait
に渡す必要があります:pids= for ... worker ... & pids+=" $!" done wait $pids || { echo "there were errors" >&2; exit 1; }
コメント
- ありますサーバーで実行されている他のジョブである必要があります。したがって、' dは、バッチを待つだけです。これらはRスクリプトであるため、
R
またはivid =で実行されます。top
コマンドの “4700a8d421″>
wait
により、bash
は、それ自体が生成したバックグラウンドジョブを待機します。ここで混乱が生じる可能性があります-これらのfor
ループは、ファイルに保存してスクリプトとして呼び出しましたか(行)、またはターミナルで手動で入力していますか?cat file.txt | while
を実行していて、pidがループの外側に設定されていませんでしたそのため、waitコマンドは空の$pids
文字列を検出しました。これが発生する理由については、 serverfault.com/q/259339 で説明されています。 serverfault.com/a/259346 while ... < files.txt
として簡単に修正できます。 pids変数を使用した+記号の目的は何ですか?回答
組み込み。バックグラウンドプロセスが終了するまで待機します。
詳細については、help fg
を試してください。
コメント
- スクリプトはジョブ制御なしで実行されます。
回答
次のコードセグメントのようなものを挿入した場合2つのfor
ループの間に、役立つ場合があります。
flag=0 while [ flag -eq 0 ] do ps -ef | grep "Rscript --vanilla" | grep -v grep > /dev/null flag=${?} sleep 10 done
もちろん、アプリケーションがRscript
が正常に完了せず、長引く可能性があります。2番目のforループが実行されない可能性があります。上記のコードセグメントは、識別子がRscript --vanilla
のすべてのプロセスが正常に完了して消えることを前提としています。アプリケーションが何を実行し、どのように実行されるかを知らなくても、私はこの仮定に頼らなければなりません。
編集
コメントに照らして、これはより適しています あなたの要望。 (元のコードと完了チェックロジックが含まれています)
for i in {1..30} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & pids[$i]=${!} done flag=0 while [ flag -eq 0 ] do for PID in $(echo ${pids[@]}) do flag=1 ps -ef | grep ${PID} | grep -v grep >/dev/null; r=${?} if [ ${r} -eq 0 ] then flag=0 fi done done for i in {31..60} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & done
コメント
- プロセス
top
の名前には、R
が表示される場合とcc1plus
が表示される場合があります。 - その場合、
ps -ef
リストに表示される共通の分母を見つける必要があります。 または、各nohup
コマンドの後で、echo ${!}
によってPIDを変数(できれば配列)に記録し、このPIDのグループを確認します。 それらがすべて消えたら、2番目のfor
ループ
に進むことができます。
wait
ビルトインを検索してください。