![bash가 간단한 명령에 대해 하위 쉘을 생성하지 않는 이유는 무엇입니까?](https://linux55.com/image/120578/bash%EA%B0%80%20%EA%B0%84%EB%8B%A8%ED%95%9C%20%EB%AA%85%EB%A0%B9%EC%97%90%20%EB%8C%80%ED%95%B4%20%ED%95%98%EC%9C%84%20%EC%89%98%EC%9D%84%20%EC%83%9D%EC%84%B1%ED%95%98%EC%A7%80%20%EC%95%8A%EB%8A%94%20%EC%9D%B4%EC%9C%A0%EB%8A%94%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
다음 두 가지 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
sleep
top
출력 리디렉션을 사용하여 동일한 동작을 재현할 수 있습니다 .
$ 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
먼저 분기하는 대신 마지막 명령을 실행할 수도 있습니다 . 왜 안되는지 모르겠습니다.
이 사례와 리디렉션 사례는 분기가 필요할 때 감지의 문제일 수 있습니다.