bash에서 (명령)과 명령의 차이점

bash에서 (명령)과 명령의 차이점

키워드 stderr리디렉션 문제와 문제에 대한 표준 솔루션을 조사하는 동안 또 다른 문제를 발견했습니다. 설명이 제공됩니다bashtimeman 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

관련 정보