プロセスが完了したらbashコマンドを実行する

プロセスが完了したらbashコマンドを実行する

GPU を使用して ML モデルをトレーニングする 2 つのスクリプトがあります。寝る前にスクリプトを開始して、夜間に実行し、朝に結果を確認したいと考えています。

しかし、GPU メモリが限られているため、並列ではなくシリアルで実行したいと考えています。

;でそれを行うことができますpython train_v1.py && python train_v2.pyが、 のトレーニングを開始したとしますtrain_v1。 トレーニングには長い時間がかかるため、2 番目のスクリプト の実装を開始して完了し、 が終了しtrain_v2.pyたら自動的に実行したいと思いますpython train_v1.py

どうすればそれを実現できるでしょうか? ありがとうございます。

答え1

ループを伴わず、他のプロセスがまだ生きているかどうかを確認したり、train_v1.py通常とは異なる方法で呼び出したりしないアプローチを次に示します。

$ python train_v1.py
^Z
[1]+  Stopped                 python train_v1.py
$ % && python train_v2.py

は、プロセスの実行中に+を押して、シグナルを送信してスリープ状態にする^Zことです。次に、をコマンドとして使用して、シェルに で起動するように指示し、最後に を追加できます。これにより、最初からを実行した場合と同じように動作します。CtrlZtrain_v1.pySIGTSTP%&& python train_v2.pypython train_v1.py && python train_v2.py

の代わりに%を使用することもできますfg。同じことです。シェルのこれらの機能について詳しく知りたい場合は、以下を参照してください。bash のマニュアルページの「ジョブ制御」セクション

編集: キューに追加し続ける方法

jamesdlin がコメントで指摘したように、train_v3.pyたとえば v2 が開始する前に追加するパターンを継続しようとすると、できないことがわかります。

$ % && python train_v2.py
^Z
[1]+  Stopped                 python train_v1.py

train_v1.py停止されるのは開始されていないからだけでありtrain_v2.py、開始されていないものを停止/一時停止/スリープ状態にすることはできません。

$ % && python train_v3.py

結果は同じになる

python train_v1.py && python train_v3.py

は最後に中断されたプロセスに対応するためです。このよう%に追加する代わりに、履歴を使用する必要があります。v3

$ !! && python train_v3.py
% && python train_v2.py && python train_v3.py

上記のように履歴を展開するか、キーバインド (up など) を使用して最後のコマンドを呼び出して、最後に v3 を追加することができます。

$ % && python train_v2.py && python train_v3.py

これを繰り返すことで、パイプラインにさらに追加することができます。

$ !! && python train_v3.py
% && python train_v2.py && python train_v3.py
^Z
[1]+  Stopped                 python train_v1.py
$ !! && python train_v4.py
% && python train_v2.py && python train_v3.py && python train_v4.py

答え2

すでに開始している場合は、を使用してそのプロセスが消えるまでポーリングし、2 番目の Python スクリプトを実行することpython train_v1.pyができます。pgrep

while pgrep -u "$USER" -fx 'python train_v1.py' >/dev/null
do
    # sleep for a minute
    sleep 60
done
python train_v2.py

と を使用すると-f-x最初の Python スクリプトを起動するために使用された正確なコマンド ラインと一致させることができます。一部のシステムでは、はオプションpgrepを実装し-q、それを静かにします ( と同様grep -q)。つまり、 へのリダイレクトは/dev/null不要になります。

この-uオプションは、一致を自分が実行しているコマンド(同じシステム上の友人や他のユーザーのコマンドではない)に制限します。

最初のスクリプトをまだ開始していない場合:

コメントで述べたように、最初のスクリプトの直後に 2 番目のスクリプトを起動することもできます。2 番目のスクリプトが存在しないか、まだ実行準備ができていないという事実は問題ではありません (最初のスクリプトが終了したときに実行準備ができている限り)。

python train_v1.py; python train_v2.py

この方法を実行すると、最初のスクリプトの終了ステータスに関係なく、2 番目のスクリプトが起動します。質問に示されているように、&&の代わりにを使用する;ことも機能しますが、2 番目のスクリプトを開始するには、最初のスクリプトが正常に終了する必要があります。

答え3

最初のスクリプトは次のように起動できます。

python train_v1.py; touch finished

次に、存在するかどうかを定期的にチェックするループを作成しますfinished

while [ ! -f finished ] ; do     
    sleep 5
done
python train_v2.py
rm finished

答え4

最初のスクリプトの終了ステータスを知る必要がない場合は、次のようなものをお勧めします。クサラナンダが書いたもの

終了ステータスを知る必要がある場合(この場合はおそらく必要ありませんが、これを行うソリューションを探している人が他にもいるかもしれません)、状況はより複雑になります。私は小さなLinuxユーティリティpwaitプロセスが終了するまで待機し、その終了ステータスを確認できます。

関連情報