bash가 간단한 명령에 대해 하위 쉘을 생성하지 않는 이유는 무엇입니까?

bash가 간단한 명령에 대해 하위 쉘을 생성하지 않는 이유는 무엇입니까?

다음 두 가지 bash 명령을 고려하십시오. 하나는 서브쉘을 생성하고 다른 하나는 생성하지 않습니다.

종자껍질 없음

$ bash -c "sleep 10000 "

pstree 출력:

bash,100648
  └─sleep,103509 10000

테이프 껍질

$ bash -c "sleep 10000; sleep 99999 "


bash,100648
  └─bash,103577 -c sleep 10000; sleep 99999
      └─sleep,103578 10000

일종의 최적화인가요? Bash는 명령을 살펴보고 간단한 명령에 대해서는 프로세스 생성을 건너뜁니다. 이 간단한 명령은 상위 터미널의 bash에 의해 생성된 것 같습니다.


내가 사용하는 Bash 버전은

$ bash --version
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)

하지만 bash 3.X에서도 같은 상황이 관찰될 수 있다고 생각합니다.


더 많은 예. 내장 명령을 사용하면 서브쉘이 생성됩니다. 내장 기능은 상위 bash에서 실행되지 않습니다.

$ bash -c "read"

bash,100648
  └─bash,104336 -c read

sleeptop출력 리디렉션을 사용하여 동일한 동작을 재현할 수 있습니다 .

$ bash -c "top -b "
bash,100648
  └─top,104392 -b

그리고

$ bash -c "top -b > /dev/null "
bash,100648
  └─bash,104420 -c top -b > /dev/null
      └─top,104421 -b

답변1

첫 번째 예에서 PID 100648이 있는 셸은 대화형 셸이며 sleep실제로는 교체 bash -c ''프로세스입니다.execve()시스템 호출호출한 원래 프로세스의 PID를 유지하는 새 프로그램을 생성하므로 bash -c ''원래 프로세스가 표시되지 않습니다. 쉘 프로세스를 간단한 명령으로 대체하는 간단한 이유는 다음에서 설명한 대로 리소스를 절약하기 때문입니다.스티븐의 대답도착하다간단한 bash 명령에 명백한 복제나 분기가 없는 이유는 무엇이며 어떻게 수행됩니까?.

이는 터미널의 간단한 테스트에서도 확인할 수 있습니다.

$ echo $$
10250
$ bash -c 'sleep 60'

다른 기사에서는:

$ pstree -p 10250
bash(10250)───sleep(21031)

왜 이런 일이 일어나는지는 파이프도 없고, 간단한 명령만 있기 때문입니다.bash 간단한 명령에 대한 직접 실행.

이러한 이유로 bash두 번째 예에서는 여러 명령문이 있음이 인식되므로 sleep"sleep 10000; sleep 99999 "번째 경우에는 execve()새 프로세스가 종료될 때 상위 프로세스를 교체하는 것이 가능합니다. 문제가 없습니다. 그러나 여기서는 첫 번째 명령이 완료된 후 셸을 종료할 수 없습니다. 따라서 sleep 10000출력에서 ​​볼 수 있는 것과 같은 포크와 execve가 있을 것이며 pstree나중에 새로운 포크와 execve가 있을 것 입니다.sleep 99999


수행할 수 있는 또 다른 테스트는 간단한 명령이 bash -c ''셸 프로세스를 대체한다고 믿는 것입니다.

$ bash -c 'grep "^Pid:" /proc/self/status /proc/$$/status'
/proc/self/status:Pid:  23946
/proc/23946/status:Pid: 23946

이 동작은 bash에만 적용됩니다. Debian 기반 배포판 의 경우 /bin/dash(에서도 확인 가능 strace):

$ sh -c 'grep "^Pid:" /proc/self/status /proc/$$/status'
/proc/self/status:Pid:  24188
/proc/24187/status:Pid: 24187

답변2

의 출력은 pstree오해의 소지가 있습니다.

bash -c "sleep 10000 "

Bash 하위 프로세스가 실제로 생성되었습니다. 그러나 프로세스는 다른 하위 프로세스를 생성하지 않습니다. 쉘을 실행한 sleep후에는 아무것도 할 필요가 없기 때문에 execve()먼저 포크하지 않고 바로 진행할 수 있습니다.sleep

execve속도가 너무 빠르기 때문에 에서 이후에만 결과를 볼 수 있습니다 pstree.

하지만

bash -c "sleep 10000; sleep 99999 "

새로운 bash 케이스는 각 명령에 대해 한 번씩, 두 번 포크됩니다. execve먼저 분기하는 대신 마지막 명령을 실행할 수도 있습니다 . 왜 안되는지 모르겠습니다.

이 사례와 리디렉션 사례는 분기가 필요할 때 감지의 문제일 수 있습니다.

관련 정보