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


20

次のような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近いそこジョブを開始しているため。代替ソリューションはありますか?


1
wait組み込みのマニュアルを検索します。
桂佐藤

回答:


22

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"

6

いくつかのポイント:

  • nohupリモートシェル出口がワーカープロセスを強制終了しないようにすることが目標である場合はnohup、スクリプトが作成する個々のワーカープロセスではなく、スクリプト自体で使用する必要があります。

  • ここで説明したようにnohupプロセスがSIGHUPを受信して​​端末と対話するのを防ぐだけですが、シェルとその子プロセスの間の関係を壊しません。

  • 上記の点のため、の有無にかかわらずnohupwait2つのforループの間の単純なループはfor、最初のループによって開始されたすべての子プロセスが終了した後にのみ実行されforます。

  • シンプルなwait

    現在アクティブなすべての子プロセスが待機され、戻りステータスはゼロです。

  • 1番目にforエラーがなかった場合にのみ2番目を実行する必要がある場合は、各ワーカーPIDを$!で保存し、それらをすべてに渡す必要がありますwait

    pids=
    for ...
        worker ... &
        pids+=" $!"
    done
    wait $pids || { echo "there were errors" >&2; exit 1; }
    

サーバー上で他のジョブが実行されている可能性があります。だから私はバッチを待つだけです。.それらはRスクリプトなので、コマンドの下Rまたはコマンドcc1plusで実行されますtop
masfenix

また、内部でnohupを使用して、すべてのコマンドを「並列」で実行したいと思います。基本的に、これらは科学プログラムのシミュレーションです。合計180のシミュレーションを実行したいのですが、60のバッチで実行します。カウンターも1から180にする必要があります。一度に1つずつ実行すると、時間がかかりすぎます。
マスフェニックス

wait原因bash、それは何も、自身を生み出していないバックグラウンドジョブを待ちます。ここに混乱があるかもしれません-これらのforループは、ファイルに保存してスクリプトとして呼び出しましたか(##script行のために私が仮定したもの)、またはターミナルで手で入力していますか?
マテイデビッド

-1

fg組み込みを使用します。バックグラウンドプロセスが完了するまで待機します。

help fg詳細をお試しください。


スクリプトはジョブ制御なしで実行されます。
クサラナナンダ

-1

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
masfenix

その場合、ps -efリストに表示される共通の分母を見つける必要があります。または、各nohupコマンドの後に、PIDを変数(できれば配列)に記録し、echo ${!}このPIDのグループを確認します。彼らはすべて消えたとき、あなたは、第二に進むことができforたループ
MelBurslan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.