前のコマンドが終了するまでbashスクリプトを一時停止する

次のような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ビルトインを検索してください。

回答

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″>
  • また、'内でnohupを使用したい" parallel "ですべてのコマンドを実行します。基本的に、これらは科学プログラムのシミュレーションです。合計180のシミュレーションを実行したいのですが、60のバッチで実行します。カウンターも1から180にする必要があります。一度に1つずつ実行すると、時間がかかりすぎます。
  • 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ループ

    に進むことができます。

    コメントを残す

    メールアドレスが公開されることはありません。 * が付いている欄は必須項目です