키워드 stderr
리디렉션 문제와 문제에 대한 표준 솔루션을 조사하는 동안 또 다른 문제를 발견했습니다. 설명이 제공됩니다bash
time
man bash
(list)
복합 명령예목록은 서브쉘 환경에서 실행됩니다.. 이제 애플릿 실행에서 볼 수 있듯이 간단한 호출을 수행하며 명령줄과 명령줄 사이에 차이가 없는 hello
것처럼 보입니다 . system("ps -opid,ppid,comm")
나는 이것이 나를 놀라게 했다. 그러나 명령이 내장 명령인 경우에는 차이가 있다는 것을 알고 있습니다. 이 경우 괄호가 없으면 분기가 발생하지 않지만, 내장 명령 주위에 괄호가 있으면 분기가 발생합니다. 내가 뭐 놓친 거 없니?(./hello)
./hello
18:59:13 -> echo $$
5323
19:34:30 -> ./hello
hello world from process ID 8657, parent ID 5323
PID PPID COMM
5323 5322 -bash
8657 5323 ./hello
19:42:34 -> (./hello)
hello world from process ID 8977, parent ID 5323
PID PPID COMM
5323 5322 -bash
8977 5323 ./hello
19:42:43 -> time (./hello)
hello world from process ID 8985, parent ID 8984
PID PPID COMM
5323 5322 -bash
8984 5323 -bash
8985 8984 ./hello
real 0m0.021s
user 0m0.003s
sys 0m0.004s
19:42:53 -> (time ./hello)
hello world from process ID 9000, parent ID 8999
PID PPID COMM
5323 5322 -bash
8999 5323 -bash
9000 8999 ./hello
real 0m0.030s
user 0m0.003s
sys 0m0.005s
19:43:05 ->
답변1
서브셸은 별도의 프로세스에서 실행된다는 보장이 없습니다. 이것은 일반적인 구현입니다.
서브쉘의 정의는 쉘이 서브쉘이 상위 쉘의 상태를 변경하지 않도록 해야 한다는 것입니다. 서브쉘은 상위 쉘의 변수, 정의된 함수, 별칭, 옵션, 기록, 제한 사항 등에 영향을 줄 수 없습니다. 가장 쉬운 방법은 별도의 프로세스에서 서브셸을 실행하는 것이므로 일반적으로 이런 일이 발생합니다. 그러나 하위 쉘이 상위 쉘의 어떤 항목에도 영향을 미치지 않는다는 것을 보장할 수 있는 경우 쉘은 별도의 프로세스를 실행할 필요가 없습니다.
대부분의 sh 구현에서는 외부 명령을 실행하는 것 외에는 아무 작업도 수행하지 않는 하위 쉘은 두 번 분기되지 않습니다.
for sh in dash bash ksh93 mksh zsh; do printf "%6s " "$sh"; "$sh" -c '(perl -e "print getppid()"); echo " $$"'; done
dash 945 945
bash 947 947
ksh93 949 949
mksh 951 951
zsh 953 953
더 복잡한 작업을 수행하면 bash는 하위 쉘을 포크하고 다시 외부 명령을 포크합니다. 일부 다른 쉘은 (트랩이 없는 한) (하위)쉘의 마지막 명령을 포크하지 않습니다.
for sh in dash bash ksh93 mksh zsh; do printf "%6s " "$sh"; "$sh" -c '(true; perl -e "print getppid()"); echo " $$"'; done
dash 1306 1306
bash 1309 1308
ksh93 1311 1311
mksh 1314 1313
zsh 1316 1316
ATT ksh( ksh93
)는 다른 쉘보다 더 최적화되어 있습니다. 제가 비교한 5개의 프로그램 중 서브쉘에서 변화하는 데이터를 추적하기 위해 동일한 프로세스에서 별도의 데이터 구조를 생성하여 최적화한 유일한 프로그램이었습니다.
for sh in dash bash ksh93 mksh zsh; do printf "%6s " "$sh"; "$sh" -c '(perl -e "print getppid()"; /bin/true); echo " $$"'; done
dash 3082 3081
bash 3085 3084
ksh93 3088 3088
mksh 3092 3091
zsh 3096 3095
프로세스 제한 변경과 같이 ATT ksh가 하위 쉘에 대한 하위 프로세스를 생성하도록 강제할 수도 있습니다.
for sh in dash bash ksh93 mksh zsh; do printf "%6s " "$sh"; "$sh" -c '(ulimit -n 42; perl -e "print getppid()"; /bin/true); echo " $$"'; done
dash 4504 4503
bash 4507 4506
ksh93 4511 4510
mksh 4515 4514
zsh 4519 4518