서브 쉘에 변수가 보이는 이유는 무엇입니까?


18

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동일한 인수가 복제 시스템 호출을 기반으로하지만이 경우 에는 동일하지 않습니다 .


vinc17은 true라고 말합니다. 서브 쉘이있을 때 pstree를 얻더라도이 문제를 믿습니다.
PersianGulf

답변:


15

Learning Bash Book이 잘못되었습니다. 서브 쉘은 모든 변수를 상속합니다. 짝수 $$(원래 쉘의 PID)도 유지됩니다. 그 이유는 (당신이 입력 할 때, 반대로 서브 쉘을 위해, 쉘은 단지 포크와 새로운 쉘을 실행하지 않는다는 것입니다 ./file하며 strace의 출력에, 봐 새 명령이 실행 예를 들어, 새로운 쉘되고, execve유사한) . 따라서 기본적으로 사본입니다 (문서화 된 차이점이 있음).

참고 : 이것은 bash에만 국한되지 않습니다. 이것은 모든 쉘에 해당됩니다.


좋아,하지만 지금은 쉘에서 strace를 시작하려고했지만 ./file을 실행하려고했지만 exec에 대한 호출을 찾을 수 없으므로 주소 공간이 두 프로세스에 대해 동일해야하므로 어떻게 설명 할 수 있습니까?
user3718463

@ user3718463 어린이도 추적 하는 -f옵션 을 사용 했습니까 strace? exec를 찾는 데 필요합니다.
vinc17

yup 감사합니다. -f 옵션이 없어서 exec sys 호출을 찾을 수 없습니다.
user3718463

16

귀하 또는 도서가 서브 쉘을 쉘인 서브 프로세스와 혼동하고 있습니다.

일부 쉘 구조는 쉘 이 하위 프로세스를 분기 시킵니다. 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.


이 대답은 나를 위해 몇 가지를 정리했습니다. 내가 이해하지 못하는 유일한 것은 두 번째 단락에서 "이 아이는 쉘 스크립트의 일부를 실행합니다."라는 문장입니다. 어떤 쉘 스크립트가 참조되고 있습니까?
flow2k

@ flow2k 쉘이 해석하는 스크립트 (예 : 프로그램).
Gilles 'SO- 악의를 멈추십시오'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.