GNU bash 버전 4.2.25(1)-릴리스(x86_64-pc-linux-gnu)를 사용하는 Ubuntu 12.04에서 다음 명령을 시도했습니다.
$ bash -c 'pstree -s $$'
init───sshd───sshd───sshd───bash───pstree
$ bash -c 'pstree -s $$;echo'
init───sshd───sshd───sshd───bash───bash───pstree
두 번째는 내 예상대로라고 생각합니다. 첫 번째 bash
는 제가 이 명령을 실행한 곳입니다. 두 번째 bash
는 내가 시작한 것입니다 bash -c ...
. 그런 다음 두 번째 bash는 이라는 하위 프로세스를 시작합니다 pstree
.
그런데 첫 번째 사건은 어떻게 되었는지 궁금합니다. 두 번째가 bash
사라지고 pstree
원본의 하위 프로세스가 된 이유는 무엇입니까 bash
? 그리고 이전 질문에 대한 답변이 두 번째 질문에는 왜 적용되지 않습니까 bash -c ...
?
답변1
나는 그것이 단순히라고 말했을 것이다.꼬리 부르다 최적화, 그러나 실제로는 (마지막 링크에서 알 수 있듯이) bash
테일 호출을 최적화하지 않습니다. 리디렉션이 있는 경우는 아니지만 실행할 명령이 간단한 명령(즉, 복합 명령이 아닌)인 경우에만 최적화된 것으로 보입니다. 또한 명령이 and-or 목록에서 마지막인 경우( true && true && cmd
or 에서처럼 false && true || cmd
) 최적화하는 것처럼 보이지만 s가 제자리에 있을 때는 trap
( 에서처럼 trap uname EXIT && cmd
) 그렇게 하는 것이 올바르지 않기 때문에 최적화되지 않는 것 같습니다.
두 번째 명령은 명령줄의 마지막 명령이 아니기 pstree
때문에 의 마무리 호출이 아닙니다. pstree
( 의 테일 콜이지만 echo
일반적 echo
으로 내장되어 있으므로 이에 관계없이 하위 프로세스가 생성되지 않습니다.)
모든 링크를 읽는 시간을 절약하기 위해(재미있기를 바라지만) 함수/프로그램/무엇이든 다른 함수/프로그램/무엇이든 호출한 후 즉시 반환되고 반환된 값은 호출된 함수/프로그램/무엇이든 반환된 값이 있으면 새 스택 프레임을 푸시(새 프로세스 생성)하는 대신 현재 스택 프레임(또는 쉘 스크립트의 경우 프로세스)을 재사용하여 함수(스크립트 실행)를 실행한 다음 반환합니다. 쉘 스크립트에서는 마지막 명령을 사용하여 수동으로 수행할 수 있지만 exec
쉘이 자동으로 수행하는 것도 가능합니다.
zsh
둘 ksh
다 그렇게 할 수 있는 것 같지만 그렇지 않습니다 bash
.
$ zsh -c 'if [[ -n foo ]]; then pstree -s $$; else echo hello; fi'
init───lightdm───lightdm───init───konsole───bash───pstree
$ ksh -c 'if [[ -n foo ]]; then pstree -s $$; else echo hello; fi'
init───lightdm───lightdm───init───konsole───bash───pstree
$ bash -c 'if [[ -n foo ]]; then pstree -s $$; else echo hello; fi'
init───lightdm───lightdm───init───konsole───bash───bash───pstree
그러나 그 관찰은 내가 우연히 설치한 쉘 버전을 기반으로 한 관찰일 뿐이므로 YMMV는 다음과 같습니다.
$ zsh --version
zsh 5.0.2 (x86_64-pc-linux-gnu)
$ ksh --version
version sh (AT&T Research) 93u+ 2012-08-01
$ bash --version
GNU bash, version 4.2.45(1)-release (x86_64-pc-linux-gnu)