基本端末をブロックせずにプロセスが終了するのを待ってから、一連のタスク(tmuxセッションの終了など)を実行するにはどうすればよいですか?

基本端末をブロックせずにプロセスが終了するのを待ってから、一連のタスク(tmuxセッションの終了など)を実行するにはどうすればよいですか?

tmux内でnohupを「再実装」しようとしています(したがって、私をブロックせずにタスクを渡してから、nohupとして機能するtmuxコマンドを終了します)。私の試みはここにあります(最初に説明したようにいくつかの問題がありますが、うまくいきません)。これは別の質問です。、この質問はスクリプトの最後の部分についてです)。私の主な問題は、バックグラウンドで実行されている実際のPythonスクリプトが完了したら、tmuxセッションを終了したいということです。私の完全な試みは次のとおりです。

# - get a job id for this tmux session
export SLURM_JOBID=$(python -c "import random;print(random.randint(0, 1_000_000))")
echo SLURM_JOBID = $SLURM_JOBID
export OUT_FILE=$PWD/main.sh.o$SLURM_JOBID
export ERR_FILE=$PWD/main.sh.e$SLURM_JOBID

# - CAREFUL, if a job is already running it could do damage to it, rm reauth process, qian doesn't do it so skip it
# top -u brando9
# pkill -9 reauth -u brando9

# - start tmux, 
https://unix.stackexchange.com/questions/724877/custom-kerberos-tmux-doesnt-let-me-name-my-sessions-help-forcing-it
tmux new -s $SLURM_JOBID
# /afs/cs/software/bin/krbtmux new -s $SLURM_JOBID
# cat /afs/cs/software/bin/krbtmux

# - reauth
# /afs/cs/software/bin/reauth
echo $SU_PASSWORD | /afs/cs/software/bin/reauth
# echo 'Secret' | /afs/cs/software/bin/reauth
# echo 'totally secret password' | kinit [email protected]
# to see reauth running
# top -u brando9 

# - expt python script
python expts.py &
python -u ~/diversity-for-predictive-success-of-meta-learning/div_src/diversity_src/experiment_mains/main_sl_with_ddp.py --manual_loads_name sl_hdb1_5cnn_adam_cl_filter_size --filter_size 4 > $OUT_FILE 2> $ERR_FILE &
export JOB_PID=$!
echo JOB_PID = $JOB_PID

# - Echo tmux id, should be jobid
tmux display-message -p '#S'
echo SLURM_JOBID = $SLURM_JOBID

# - detach current tmux session
tmux detach &

# - wait for pid from python to be done, if done kill this tmux sess
wait $JOB_PID
tmux ls
tmux kill-session -t $SLURM_JOBID
# check it was killed
tmux ls

# - Done
echo "Done with bash script (experiment or dispatched daemon experiments). "

しかし、上記はうまくいきません。 Pythonスクリプトが実行されスケジュールされたら、&私が望むのは、そのタスクが完了した後にtmuxセッションを終了することです。ついに試してみましたが、効果があるかどうか疑問でした。一度実行すると、tmux detach &tmuxセッションを終了し、wait ...tmuxの外部でコマンドを実行してデフォルトの端末をブロックするため、機能しないようです。代わりに、私が望むのは、tmux内でwaitコマンドを実行し(私をブロックしないように)、Pythonスクリプトが完了したらtmuxセッションを完全に終了することです。しかし、これは私のスクリプトの最後にコンテキストを追加するだけです。

どのように動作させることができますか?

関連:パスワードが必要なコマンドを使用してLinuxで認証するには?

答え1

;演算子を使用してコマンドを連結し、&演算子を使用してバックグラウンドで送信できます。グループ全体をバックグラウンドで送信するには、コマンドを括弧で囲みます。以下はデモです:

tmux new -s test
(sleep 15 ; tmux kill-session -t test) &
tmux detach

while true ; do 
  if ! tmux ls 2> /dev/null | grep 'test:' ; then
    echo tmux test disconnected
    break
  fi
  sleep 1 # limit polling rate
done

答え2

プロセス間の親子関係が必要なためwait、この特別な方法では使用できません。 alsoをwait使用すると、;これはコマンド区切り文字にすぎず、機能しません。つまり、プロンプトが返されるまでコマンドを完了する必要があります。

代わりに、私はあなたが探しているものが単に次の例のようなものだと思います。

### Random SLURM_JOBID value
export SLURM_JOBID=$(python3 -c "import random;print(random.randint(0, 1_000_000))")

### Init tmux session
tmux new -s "$SLURM_JOBID"
### --- tmux session ---
### Test command: runs in the background of a detached tmux session 
### and once finished will self-destruct that same detached tmux session

(for  i in $(seq 1 30); do sleep 1 ; done && tmux kill-session -t "$SLURM_JOBID" ) & tmux detach

上記のコマンドを実行すると、すぐにtmuxで始まるシェルに戻ります。

実行 - ループの30秒の実行時に、次のコマンドはtmux実際にはまだバックグラウンドに存在することを確認します(次をtmux attach使用して再接続することもできます)。

> ps aux | grep tmux
user       12579  0.0  0.0   5880  3928 ?        Ss   10:26   0:00 tmux
user       12613  0.0  0.0   3876  1836 pts/0    S+   10:27   0:00 grep --color=auto tmux

> tmux list-sessions
683635: 1 windows (created Wed Nov 30 10:26:02 2022)

30秒後に同じコマンドを実行すると、親セッションがもうtmux存在しないことが確認されます。

> ps aux | grep tmux
user       12706  0.0  0.0   3876  1836 pts/0    S+   10:30   0:00 grep --color=auto tmux

> tmux list-sessions
no server running on /tmp/tmux-0/default



コマンド構文の説明
(for  i in $(seq 1 30); do sleep 1 ; done && tmux kill-session ) & tmux detach

上記のコマンドにはいくつかのユニークな側面があり、1つずつ議論しましょう。

  • パート1: [CMD1] && [CMD2]

上記のコマンドの文脈では、これは次のとおり[CMD1]です[CMD2]

[CMD1] =for i in $(seq 1 30); do sleep 1 ; done

[CMD2] =tmux kill-session -t "$SLURM_JOBID"

2つの異なるコマンド間でデュアルアンパサンドを使用すると、シェルが正常に完了した場合にのみif ANDを[CMD1] && [CMD2]待って実行します。[CMD2][CMD1]

つまり、私たちのコマンドの文脈では、シェルはループを開始し、30回繰り返し実行し、sleep 1ループが完了したら実行するように指示しますtmux kill-session

セッション内で次のコマンドの組み合わせを実行して、tmuxこの動作を直接テストできます。

for  i in $(seq 1 10); do sleep 1 ; done && tmux kill-session 

ループは、プロンプトを維持しながら前景から開始して実行されます。

10秒間実行して完了したら、残りのtmux kill-session部分を実行し、自分の&&セッションtmuxを削除して前のシェルに戻ります。

一方CTRL、+を送信してz実行中にループを終了すると、シェルはSIGINTを失敗として登録し、右側のSIGINT実行を許可しないtmuxため、セッションは1日の間維持されます。[CMD1][CMD2]&&


  • パート2: ( [CMD1] && [CMD2] )

複数のコマンドの周りに括弧を使用すると、コマンドをグループ化して分離できるため、数学演算の順序と同様の動作を実行できます。


  • パート3: ( [CMD1] && [CMD2] ) &

角かっこの後に「&」を追加すると、バック&グラウンドで角かっこ内のすべての項目を実行できます。

を使用しないと、バックグラウンドで複数のコマンドを実行する方が面倒で複雑になります。たとえば、単にまたはを(...)使用できないからです。[CMD1] & && [CMD2][CMD1] && & [CMD2]

一方、(...)これを使用すると、次のような複雑な操作も実行できます。

((for  i in $(seq 1 5); do sleep 1 ; done && echo "first loop finished" )  && ( for i in $(seq 1 5); do sleep 1; done && echo "second loop finished" ) && sleep 5 && tmux kill-session ) &

最初のループを実行し、完了するとステータスを報告し、2番目のループを開始し、完了するとステータスも報告され、5秒sleep遅れた後にセッションはそれ自体が破棄されます。

  • パート4: ([CMD1] && [CMD2]) & tmux detach

最後の追加は、セッションを開始したシェルにtmux detach戻ることができるようにすることです。tmux2つの別々の行で次の2つのコマンドを実行して同じ動作を得ることができることは言及する価値があります。

(for  i in $(seq 1 30); do sleep 1 ; done && tmux kill-session -t "$SLURM_JOBID" ) &
tmux detach

&シングルが私たちのシングルラインの左側にあるので、順番に 。

関連情報