2014-09-27 2 views
3

학습 강타 책은 서브 쉘은 환경을 상속 언급은 variabels 및 파일 기술자, ... 등 그리고 내가 알고있는배쉬 서브 쉘 신비

$ var=15 
$ (echo $var) 
15 
$ ./file # this file include the same command echo $var 

$ 

의 수출하지 않는 변수를 상속하지 않습니다 shell은() case와 ./file을위한 두 개의 서브 쉘을 만들지 만,() 케이스에서는 export되지 않고 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는해야 부모의 프로세스 주소 공간이 같아서 왜 varible이 서브 쉘에 보이고 동일한 인수가 복제 시스템 호출에 기반을 두지 만 ./file의 경우에는 발생하지 않습니다.

일단 수출, 변수가 실행시에 모든 아이들 공정에 사용되는
export var=15 

(시간을 내 보내지) :

+0

()에 대한 strace는 어떻게 했습니까? –

답변

3

서브 쉘이 하지이 새로운 프로세스에 대한 execve() 전화를 사용합니까 괄호를 사용하여 만든 스크립트의 호출을 수행합니다. 이 시점에서 상위 쉘의 변수는 다르게 처리됩니다. execve()execve() (괄호의 경우)을 호출하지 않고 고의적 인 변수 집합 (스크립트 호출 사례)을 전달하여 변수의 전체 집합을 그대로 유지합니다.

strace을 사용하는 탐색은 정확히 그 차이를 보여줬을 것입니다. 당신이 그것을 보지 않았다면, 나는 당신이 몇 가지 가능한 실수 중 하나를 만든 것으로 가정 할 수 있습니다. 나는 그 차이를 보여주기 위해 한 일을 그냥 털어 놓을 것이고, 그때 당신은 자신이 어디에 있었는지 잘못 결정할 수 있습니다.

나는 두 개의 흔적을 만들었습니다.첫 번째는

strace -f -o bash-mystery-1.strace bash -c 'v=15; (echo $v)' 

strace -f -o bash-mystery-2.strace bash -c 'v=15; ./x.sh' 

사용하여 수행 된 두 번째 사용하여 수행되었다 (x.sh가 실행 스크립트 인과 함께.)

옵션 -f 부모 쉘의 아이들을 추적 할 필요가 있었다 (명령 행에서 bash).

주소 같은 모든 일반적인 자주 차이를 균등 후 나는 diff -y -W 300로 비교 이러한 흔적와의 PID :

q() { 
    sed -e 's/0x[0-9a-f]*/ADDR/g' \ 
     -e 's/12923\|12927/PARENT/g' \ 
     -e 's/12924\|12928/CHILD/g' 
} 
diff -y -W 300 <(q < bash-mystery-1.strace) <(q < bash-mystery-2.strace) | less -S 

12923 및 12927 내 부모의 PID 및 12,924했고 12928 내가 발견 내 아이의 PID (했다 추적 파일을 스캔하여). 물론 다른 숫자가 있으므로이 값을 조정하십시오. 그리고 diff 출력을 제대로보기 위해서는 매우 넓은 터미널 (200 자 이상)이 필요합니다. 그래서 너의 창문을 넓게 만들어라 ;-)

나는 clone() 전화를 찾는다. 이것은 fork()인데, 현재의 프로세스를 두 개로 나눈다. 그곳에서 아이들은 흔적을 따라 다음과 같은 행에서 일을 시작합니다. 165 행 부근에서 저는 execve()이라는 전화를 보았습니다 만, 대본을 요구하는 사례의 흔적에서만 볼 수 있습니다. 그래서 그곳에서 자발적으로 많은 환경을 포기하고 의도적으로 설정합니다. 괄호 대/소문자는 환경을 변경하지 않으며 (execve()을 호출하지 않음) 자식 프로세스는 계속 전체 집합을 유지합니다.

2

당신은 자식 프로세스에 대한 귀하의 var를 내보낼 수 있습니다. 수출 unset을 이용하여 상쇄 될 수

export var=15 

export var 
var=15 

가 동일

var=15 
export var 

는 동일하다. 샘플 : unset var.

+2

이 질문과 어떤 관련이 있습니까? – bobah

+0

내 대답부터 질문이 수정되었습니다 ... –

+2

답장을 보내 주셔서 감사합니다. 그러나 scences 뒤에서 실제로 일어나고있는 것이 무엇인지 알고 싶습니다. – user3718463

1

이 비밀에 대한 해결책은 부모 쉘과 같은 메모리 공간을 공유 그래서 그들은 단순히 포크 또는 복제를 호출하기 때문에 서브 쉘이이

작동합니다 그 이유는, 모든 쉘 변수를 포함하여 부모 쉘에서 모든 것을 상속입니다

그러나 ./file에서

$ var=15 
$ (echo $var) 
15 
는 서브 쉘은 나중에 이전의 모든 부모 변수를 취소 할 간부 또는 execv와 시스템 호출 다음에하지만 우리는 여전히 -f 사용 strace를 사용하여이 확인하실 수 있습니다 환경 변수를가집니다 자식 하위 셸을 모니터링하면 execv에 대한 호출이 있음을 알 수 있습니다

[pid 26387] execve("./file", ["./file"], [/* 75 vars */]) = -1 ENOEXEC (Exec format error) 
+0

5 분 후에 나를 이길 수 있습니다. + + – Alfe

+1

하하하 절대 신경 쓰지 마세요^_ ^, 설명해주십시오. 내가 한 것보다 낫고 더 분명하게 해. – user3718463