Learning Bash Book은 서브 쉘이 환경 변수 및 파일 디스크립터 등 만 상속하고 내 보내지 않은 변수는 상속하지 않는다고 언급합니다.
$ var=15
$ (echo $var)
15
$ ./file # this file include the same command echo $var
$
아시다시피 셸은 for ()
및 for에 대해 두 개의 하위 셸을 만들지 ./file
만, 왜 하위 셸 ()
에서 var
변수를 내 보내지 ./file
않았지만 식별하지 않은 경우 에도 변수를 식별합니까?
# Strace for ()
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24558b1a10) = 25617
# Strace for ./file
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24558b1a10) = 25631
내가 사용하려고 strace
의 갈래 과정 모두 있음이 수단, 그래서 이런 방법을 알아 내기 위해 놀라 울 정도로 그 bash는 복제 시스템 호출에 동일한 인수를 사용 발견 ()
하고 ./file
왜, 부모의 같은 프로세스 주소 공간이 있어야합니다 이 ()
경우 변수가 서브 쉘에 표시되고 ./file
동일한 인수가 복제 시스템 호출을 기반으로하지만이 경우 에는 동일하지 않습니다 .
답변
Learning Bash Book이 잘못되었습니다. 서브 쉘은 모든 변수를 상속합니다. 짝수 $$
(원래 쉘의 PID)도 유지됩니다. 그 이유는 (당신이 입력 할 때, 반대로 서브 쉘을 위해, 쉘은 단지 포크와 새로운 쉘을 실행하지 않는다는 것입니다 ./file
하며 strace의 출력에, 봐 새 명령이 실행 예를 들어, 새로운 쉘되고, execve
유사한) . 따라서 기본적으로 사본입니다 (문서화 된 차이점이 있음).
참고 : 이것은 bash에만 국한되지 않습니다. 이것은 모든 쉘에 해당됩니다.
답변
귀하 또는 도서가 서브 쉘을 쉘인 서브 프로세스와 혼동하고 있습니다.
일부 쉘 구조는 쉘 이 하위 프로세스를 분기 시킵니다. Linux에서는 로그 에서 관찰 된 fork
보다 일반적인 clone
시스템 호출 의 특수한 경우입니다 strace
. 자식은 셸 스크립트의 일부를 실행합니다. 자식 프로세스를 서브 쉘 이라고합니다 . 가장 직접적인 같은 구조이다 command1 &
: command1
부모 쉘에서 실행 서브 쉘에서 실행되며, 후속 명령. 서브 쉘을 작성하는 다른 구성에는 명령 대체 $(command2)
및 파이프 command3 | command4
( command3
서브 쉘에서 command4
실행 , ksh 또는 zsh가 아닌 대부분의 쉘에서 서브 쉘에서 실행)가 포함됩니다.
서브 쉘은 상위 프로세스의 사본이므로 동일한 환경 변수뿐만 아니라 변수 ( $$
원래 쉘 프로세스의 프로세스 ID 포함 ), 함수, 별명, 옵션 등 내부 정의도 모두 동일 합니다. 서브 쉘에서 코드를 실행하기 전에 bash는 변수 BASHPID
를 하위 프로세스의 프로세스 ID로 설정합니다 .
를 ./file
실행하면 외부 명령이 실행됩니다. 먼저, 쉘은 자식 프로세스를 분기합니다. 다음이 자식 프로세스를 실행 합니다 (와 execve
실행 파일 시스템 호출) ./file
. 자식 프로세스는 환경, 현재 디렉토리 등 부모의 프로세스 속성을 상속받습니다. 응용 프로그램의 내부 측면은 execve
호출 에서 손실됩니다. 내보내지지 않은 변수, 함수 등은 커널이 알지 못하는 bash 개념입니다. bash가 다른 프로그램을 실행할 때 손실됩니다. 다른 프로그램이 bash 스크립트 인 경우에도 상위 프로세스가 bash의 인스턴스가되는지 알거나 신경 쓰지 않는 새로운 bash 인스턴스에 의해 실행됩니다. 따라서 쉘 변수 (내보내기되지 않은 변수)는 살아남지 못합니다 execve
.