편집하다

편집하다

다른 쉘 인스턴스에서 환경 변수를 설정하고 싶습니다. 그래서 나는 조사를 좀 해보기로 결심했습니다. 기사를 읽은 후숫자~의질문~에 대한이것나는 그것을 시험해 보기로 결정했다.

두 개의 쉘 A와 B(PID 420)를 생성했으며 둘 다 zsh쉘 AI에서 다음 명령을 실행합니다.

sudo gdb -p 420
(gdb) call setenv("FOO", "bar", 1)
(gdb) detach

실행하면 쉘 B에서 envFOO 변수에 bar 값이 설정되어 있는 것을 볼 수 있습니다. 이로 인해 쉘 B 환경에서 FOO가 성공적으로 초기화되었다고 생각됩니다. 그러나 FOO를 인쇄하려고 하면 아직 설정되지 않았음을 나타내는 빈 줄이 나타납니다. 나에게는 여기에 모순이 있는 것처럼 느껴진다.

이것은 내 Arch GNU/Linux 시스템과 Ubuntu VM에서 테스트되었습니다. 또한 bash변수가 환경에 나타나지 않는 경우에도 이것을 테스트했습니다. 실망스럽긴 하지만, 쉘이 빌드 시 환경의 복사본을 캐시하고 그 복사본만 사용했다면(링크된 질문 중 하나에서 제안됨) 의미가 있습니다. zsh변수가 표시되는 이유는 여전히 답변되지 않습니다 .

출력이 echo $FOO비어 있는 이유는 무엇입니까?


편집하다

댓글에 이것을 입력한 후 좀 더 테스트를 하기로 결정했습니다. 결과는 아래 표에 나와 있습니다. 첫 번째 열은 FOO변수가 주입된 쉘입니다. 첫 번째 줄에는 명령이 포함되어 있으며 그 출력은 아래에서 볼 수 있습니다. 변수는 FOO다음을 사용하여 주입되었습니다 sudo gdb -p 420 -batch -ex 'call setenv("FOO", "bar", 1)'. zsh: 특정 명령 zsh -c '...'도 bash를 사용하여 테스트되었습니다. 결과는 동일하며 간결성을 위해 해당 출력은 생략됩니다.

아치 GNU/Linux, 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이 컨텍스트에서는 셸에 따라 매우 다른 동작이 있습니다. 이 테스트가 다른 사람들에게도 도움이 되기를 바랍니다.

답변1

getenv()대부분의 쉘은 // setenv()API를 사용하지 않습니다 putenv().

시작 시 수신하는 모든 환경 변수에 대해 쉘 변수를 생성합니다. 이는 추가 정보(예: 변수를 내보냈는지, 읽기 전용인지 여부)를 전달해야 하는 내부 구조에 저장됩니다... 이를 달성하기 위해 libc를 사용할 수 없습니다 environ.

또한 이러한 이유로 명령을 실행하기 위해 를 사용하지 않고 execlp()직접 execvp()시스템 호출을 호출하여 내보낸 변수 목록을 기반으로 배열을 계산합니다 execve().envp[]

따라서 gdb셸의 내부 변수 테이블에 항목을 추가하거나 코드를 해석하여 export VAR=value테이블 자체를 업데이트하도록 올바른 함수를 호출해야 합니다.

및 를 호출할 때 차이가 나타나는 이유는 bash입력할 때와 같이 셸이 초기화되기 전에 호출했기 때문인 것 같습니다.zshsetenv()gdbsetenv()main()

bash의 는 main()이고 해당 환경 변수의 변수를 매핑하는 int main(int argc, char* argv[], char* envp[])반면 , 의 는 이고 그로부터 변수를 가져옵니다 . 수정 은 하지만 내부에서는 수행되지 않습니다(여러 시스템 및 이러한 포인터가 가리키는 문자열에서 읽기 전용).bashenvp[]zshint main(int argc, char* argv[])zshenvironsetenv()environenvp[]

그럼에도 불구하고 environ쉘이 시작되는 시점을 읽은 후에는 그 이후에는 쉘이 더 이상 사용되지 않으므로 (또는 ) 사용 setenv()에는 아무런 효과가 없습니다 .environgetenv()

관련 정보