한 쉘 인스턴스의 환경 변수를 다른 쉘 인스턴스에서 설정하는 데 관심이 있습니다. 그래서 연구를하기로 결정했습니다. 읽은 후 수 의 질문 에 대한 이 나는 그것을 테스트하기로 결정했다.
나는 두 개의 쉘 A와 B (PID 420)를 생성했으며 둘 다 실행 중 zsh
입니다. 쉘 AI에서 다음을 실행했습니다.
sudo gdb -p 420
(gdb) call setenv("FOO", "bar", 1)
(gdb) detach
셸 B에서 실행 env
하면 변수 FOO가 실제로 bar 값으로 설정되어 있음을 알 수 있습니다. 이것은 쉘 B의 환경에서 FOO가 성공적으로 초기화되었다고 생각합니다. 그러나 FOO를 인쇄하려고하면 빈 줄이 설정되어 있지 않음을 나타냅니다. 나에게는 모순이있는 것처럼 느낍니다.
이것은 내 자신의 Arch GNU / Linux 시스템과 Ubuntu VM 모두에서 테스트되었습니다. 또한 bash
변수가 env에 표시되지 않은 곳 에서도 이것을 테스트했습니다 . 이것은 나에게 실망 스럽지만 쉘이 생성시 환경의 사본을 캐시하고 그 링크 만 사용하면 (연관된 질문 중 하나에서 제안 된) 의미가 있습니다. 이것은 여전히 zsh
변수를 볼 수있는 이유에 대한 답변이 아닙니다 .
출력이 왜 echo $FOO
비어 있습니까?
편집하다
의견을 입력 한 후 조금 더 테스트하기로 결정했습니다. 결과는 아래 표에서 확인할 수 있습니다. 첫 번째 열에는 FOO
변수가 주입 된 쉘이 있습니다. 첫 번째 행에는 그 아래에 출력을 볼 수있는 명령이 포함됩니다. 변수 FOO
는 다음을 사용하여 주입되었습니다 sudo gdb -p 420 -batch -ex 'call setenv("FOO", "bar", 1)'
. zsh :에 특정한 명령 zsh -c '...'
은 bash를 사용하여 테스트되었습니다. 결과는 동일했고 결과는 간결하게 생략되었습니다.
아치 GNU / 리눅스, zsh 5.3.1, bash 4.4.12 (1)
| | env | grep FOO | echo $FOO | zsh -c 'env | grep FOO' | zsh -c 'echo $FOO' | After export FOO |
|------|------------------|-----------|---------------------------|----------------------|-----------------------------------|
| zsh | FOO=bar | | FOO=bar | bar | No Change |
| bash | | bar | | | Value of FOO visible in all tests |
우분투 16.04.2 LTS, zsh 5.1.1, bash 4.3.48 (1)
| | env | grep FOO | echo $FOO | zsh -c 'env | grep FOO' | zsh -c 'echo $FOO' | After export FOO |
|------|------------------|-----------|---------------------------|----------------------|-----------------------------------|
| zsh | FOO=bar | | FOO=bar | bar | No Change |
| bash | | bar | | | Value of FOO visible in all tests |
위의 결과는 분포에 무관심하다는 것을 암시하는 것 같습니다. 이것은 더 이상 말하지 않습니다 zsh
및 bash
다른 변수의 핸들을 설정. 또한 export FOO
셸에 따라이 컨텍스트에서 동작이 매우 다릅니다. 이 테스트가 다른 사람에게 분명한 것이 될 수 있기를 바랍니다.
답변
대부분의 쉘은 getenv()
/ setenv()
/ putenv()
API를 사용하지 않습니다 .
시작시 각 환경 변수에 대한 쉘 변수를 작성합니다. 그것들은 변수가 익스포트되는지, 읽기 전용인지와 같은 다른 정보를 전달할 필요가있는 내부 구조에 저장 될 것입니다. 그것들은 libc를 사용할 수 없습니다 environ
.
마찬가지로, 그 이유는 그들이 사용하지 않는 execlp()
, execvp()
명령을 실행할 수 있지만, 전화 execve()
컴퓨팅 직접 시스템 호출 envp[]
들이 보낸 변수의리스트에 기초하여 배열.
따라서에서 gdb
셸 내부 변수 테이블에 항목을 추가하거나 export VAR=value
해당 테이블을 자체적으로 업데이트 하는 코드를 해석하는 올바른 함수를 호출해야 할 수도 있습니다.
왜 전화를 걸었 을 때 bash
와 zsh
전화를 걸었 setenv()
을 때 차이 gdb
가 나는지 setenv()
에 대해서는 쉘 초기화 전에 전화를 걸었 기 때문 main()
입니다.
당신은 알 수 bash
‘들 main()
입니다 int main(int argc, char* argv[], char* envp[])
(그리고 bash
그 ENV가에 바르에서 변수를 매핑 envp[]
) 동안 zsh
‘이다이야 int main(int argc, char* argv[])
와 zsh
에서 변수를 가져옵니다 environ
대신. setenv()
내부에서 수정 environ
하지만 수정할 수는 없습니다 envp[]
(포인터가 가리키는 문자열뿐만 아니라 여러 시스템에서 읽기 전용).
쉘이 읽은 후에 어떤 경우에는 environ
시작할 때, 사용하는 것은 setenv()
더 이상 사용 쉘 등의 효과가있을 것 environ
(또는 getenv()
) 이후.