bash와 zsh 사이의 서브쉘 및 &&의 다양한 동작

bash와 zsh 사이의 서브쉘 및 &&의 다양한 동작

서브셸에서 명령을 실행하는 방법에 대한 나의 이해는 현재 셸이 분기된 다음 서브셸이 fork필요한 exec명령을 추가로 실행한다는 것입니다.

Bash 및 zsh에서 다음 명령을 실행할 때 이상한 동작이 나타납니다.
$ ( sleep 5 && sleep 6 )

달려갈 때세게 때리다:

$ echo $$
6410
$ ( sleep 5 && sleep 6 )

ps다음을 고려하면:
CMD: sleep 5
PID:6590
생산자 PID:6589

그런 다음:
CMD: 절전 6
PID:6616
생산자 PID:6589

이 모든 것이 나에게 의미가 있습니다. sleep 5그리고 sleep 6둘 다 동일한 상위(아마도 하위 쉘)를 갖습니다.

그러나다루기 힘든, 다음 정보를 얻습니다.

$ echo $$
1987
$ ( sleep 5 && sleep 6 )

ps다음을 고려하면:
CMD: sleep 5
PID:7576
생산자 PID:7575

그런 다음:
CMD: 절전 6
PID:7575
생산자 PID:1987년

sleep 5실행하는 데 사용된 프로세스가 sleep 6원래 쉘을 상위로 갖고 있는 반면 실행에 사용된 프로세스는 sleep 6원래 쉘을 상위로 갖는 이유를 알 수 없습니다 .

답변1

Bash에서 다음과 같은 것을 얻을 수 있습니다.

$ echo $$
26328
$ ( /bin/sleep 1234 )
$ ps -o pid,ppid,stat,args -C sleep
  PID  PPID STAT COMMAND
26473 26328 S+   /bin/sleep 1234

Bash가 하는 일은 하위 쉘에 대해 자체적으로 분기하는 동안 하위 쉘에서 단 하나의 명령만 실행할 수 있음을 인식한 다음 sleep최적화로 자체 실행하여 추가 분기를 절약한다는 것입니다. 같은 일이 비슷한 일에도 효과가 있다bash -c '/bin/sleep'

Bash는 를 사용하여 하나의 명령에 대해서만 이 작업을 수행하며 ( true; /bin/sleep 2345 )중간 쉘 프로세스도 볼 수 있습니다. 분명히 zsh는 최적화에 더 공격적이며 목록의 마지막 명령 포크를 건너뜁니다.


그러나 서브쉘이 다른 쉘 내에서 실행될 필요는 없습니다.프로세스. 그냥 다른 곳에서 실행되고 있는 것 뿐이야쉘 실행 환경, 에서POSIX 쉘 언어 사양. 이제 환경에는 umask(운영 체제 수준의 프로세스별 항목) 및 셸 변수 등이 포함되므로 분기를 통해 별도의 환경을 구현하는 것은단순한방법. 그러나 이는 필수 사항은 아닙니다.

예를 들어 ksh는 다른 작업을 수행합니다. 이 간단한 하위 쉘에는 분기가 전혀 없습니다. 하지만 여전히 작동합니다. 우리가 얻는 값은 FOO셸에서 가져옵니다.

$ strace -etrace=clone,fork,vfork -f ksh -c 'FOO=out; ( FOO=in; true ); echo "$FOO"'
out
+++ exited with 0 +++

Bash와 zsh가 거기서 포크됩니다. ksh도 sleep내장으로 구현되므로 명시적으로 사용하지 않는 한 해당 프로세스를 볼 수 없습니다 /bin/sleep.

관련 정보