`cmd1 && cmd2 && cmd3` 체인을 우아하게 일시 중지하고 다시 시작하는 방법은 무엇입니까?

`cmd1 && cmd2 && cmd3` 체인을 우아하게 일시 중지하고 다시 시작하는 방법은 무엇입니까?

~에서이전 질문&&올바르게 상호 작용하는 방법을 이해할 수 없는 것 같습니다 ^Z.

$ command1 && command2 && command3
Running command1 ...
Running command2 ...^Z
[1]+  Stopped
$ fg && command4
Running command3
Running command4

, 체인이 시작된 후 "추가"하는 데 사용할 수 있다고 생각하는 것은 command3마지막 명령이고 중지하기 때문에 작동하는 것 같습니다. command2예를 들어 누가 다른 결과를 제공합니까( command3누가 무시해야 하는지).

&&나머지 명령을 취소하지 않고 체인을 정상적으로 일시 중단하는 방법은 무엇입니까 ? 또한 명령줄에 추가 논리가 필요한 경우 종료 코드를 보존하고 싶습니다.

체인을 일찍 일시 중지하고 싶을 수도 있다는 것을 알았다면 다음과 같이 시작할 수 있으므로 ( command1 && command2 && command3 )정상적으로 일시 중지되어야 합니다. 그런데 바로 시작하면 어떻게 해야 하나요?

명령이 출력을 제공하지 않고(위의 예와 달리) 두 번 실행되어서는 안 되며 순서가 잘못되면 내가 생각할 수 있는 유일한 방법은 을 누르고 ^Z무엇이 중지되었는지 분석한 다음 수동으로 빌드하는 것입니다. fd && the_rest_of_commands이는 불편하고 틀리기 쉬움 .

답변1

무슨 일인지 오해하고 계신 것 같아요. 이 작업을 수행할 때:

cmd1 && cmd2

쉘은 cmd1하위 프로세스에서 시작하여 해당 프로세스를 기다린 다음 cmd2종료 상태가 0인 상태로 종료되면 시작됩니다.cmd1

를 누르면 Ctrl+Zwait가 반환되고 쉘은 $?148(예: (128 + SIGTSTP))로 설정되고 나머지 평가는 완료됩니다.그 순간,역시 cmd2이렇습니다아니요처형되다. 그리고 cmd1백그라운드 작업이 됩니다.

다음을 입력하는 경우:

cmd1 || cmd2

또는:

cmd1; cmd2

cmd2처형될 것이다~ 위에Ctrl-Zfg그리고 다음 프롬프트( 또는 bg가능한 경우 백그라운드 작업)를 받기 전에 완료될 때까지 기다려야 합니다 .

에서 을 zsh누르면 Ctrl-Z:

{cmd1 && cmd2 && cmd3}

그러면 전체 그룹이 일시 중지되고 하위 쉘로 이동됩니다. 그러나 재개 시 보류 중인 명령은 종료 시 종료 상태에 관계없이 20으로 설정되며 $?, 이 문제를 해결할 방법이 없다고 생각하므로 결국 동일한 동작이 발생 {cmd1 || cmd2}합니다(cmd2 에서는 ) 에서 직접 실행되는 것이 아니라 cmd1 )이 완료된 후에 실행됩니다 Ctrl-Z.

답변2

gdb -p와 일치하는 우아한 일시 중지를 제공하여 현재 실행 중인 구성 요소를 일시 중지하는 것처럼 보입니다 kill -STOP.

따라서 현재 실행 중인 작업이 무엇인지 알고 있다면 command2다음을 수행할 수 있습니다.

gdb -p $(pgrep -f 'command2')

다른 터미널에서 일시 중지하고 GDB 재개를 종료하거나 재개하세요.

답변3

명령을 실행한 대화형 셸인 상위 셸을 일시 중지할 수 있습니다.

명령을 실행하기 전에 PID를 인쇄하십시오(또는 나중에 PID를 찾으십시오. 아래 참조).

$ echo $$
1234

다른 터미널에서 대화형 쉘을 일시 중단하여 전체 명령 목록(목록은 대화형 쉘의 하위 프로세스로 구성됨)을 중지할 수 있습니다.

$ kill -STOP 1234

그리고 명령 목록을 계속 진행하세요.

$ kill -CONT 1234


유스 케이스의 중요한 부분인 명령 목록(예:)을 실행하기 전에 준비가 필요하지 않으므로 echo $$목록이 이미 포그라운드에서 실행 중일 때 중지하려는 셸의 PID를 가져오는 방법은 다음과 같습니다.

아이디어는 목록에서 모든 명령의 상위 프로세스 PID를 찾는 것입니다.

먼저 pgrep현재 실행 중인 명령의 PID를 찾는 데 사용합니다. 한 번에 하나만 실행되므로 이들 중 PID를 찾는 것으로 충분합니다.

$ pgrep 'command1|command2|command3'

command1etc가 실제로 프로세스의 명령 이름이 아닌 경우 (예: 명령줄의 첫 번째 단어) 해당 -f옵션을 추가해야 합니다( -a실험을 통해 PID 이상을 확인하려면).

$ pgrep -f 'command1|command2|command3'

ps그런 다음 find 명령의 상위 PID를 사용합니다 .

$ ps -o ppid= 

결합하면 다음과 같이 일시중단할 쉘의 PID를 얻을 수 있습니다.

$ pid=$(ps -o ppid= $(pgrep 'command1|command2|command3'))

모든 것을 한 번에:

$ kill -STOP $(ps -o ppid= $(pgrep 'command1|command2|command3'))
$ kill -CONT $(ps -o ppid= $(pgrep 'command1|command2|command3'))

관련 정보