기본 터미널을 차단하지 않고 프로세스가 끝날 때까지 기다린 다음 일련의 작업(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 부: [CMD1] && [CMD2]

위 명령의 맥락에서 이는 다음과 [CMD1]같습니다 [CMD2].

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

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

두 개의 서로 다른 명령 사이에 이중 앰퍼샌드를 사용하면 쉘이 성공적으로 완료된 경우에만 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때문에 세션이 하루 동안 계속 유지됩니다 .[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 ) &

첫 번째 루프를 실행하고 완료되면 상태를 보고한 다음 두 번째 루프를 시작하고 완료되면 상태도 보고되며 5초 sleep지연 후 세션이 자체적으로 삭제됩니다.

  • 4부: ([CMD1] && [CMD2]) & tmux detach

마지막 추가 사항은 세션을 시작한 셸로 tmux detach돌아갈 수 있도록 하는 것 입니다. tmux두 개의 개별 라인에서 다음 두 명령을 실행하여 동일한 동작을 얻을 수도 있다는 점은 언급할 가치가 있습니다.

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

&싱글이 우리 싱글 라인의 왼쪽에 속하기 때문에 차례로 .

관련 정보