~에서이전 질문&&
올바르게 상호 작용하는 방법을 이해할 수 없는 것 같습니다 ^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'
command1
etc가 실제로 프로세스의 명령 이름이 아닌 경우 (예: 명령줄의 첫 번째 단어) 해당 -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'))