답변1
귀하의 가정은 쉘 변수가환경에서. 이것은 정확하지 않습니다. 이 export
명령은 환경의 이름을 정의합니다. 그러므로:
a=1 b=2
export b
최신 결과입니다껍데기$a
1과 2로 확장될 것이라는 것을 알고 있지만 하위 프로세스는 환경의 일부가 아니기 때문에(현재 셸에서도) $b
아무것도 알지 못합니다 .a
몇 가지 유용한 도구:
set
: 현재 쉘의 매개변수를 보는 데 사용됩니다(내보냈거나 내보내지 않음).set -k
: 세트지정된 매개변수환경에서. 고려하다f() { set -k; env; }; f a=1
set -a
: 환경에 설정된 이름을 입력하도록 쉘에 지시합니다.export
모든 임무 전과 마찬가지로 . 와 같은 파일 에.env
유용합니다set -a; . .env; set +a
.export
: 환경에 이름을 입력하도록 쉘에 지시합니다. 내보내기와 할당은 완전히 다른 작업입니다.env
: 외부 명령으로서env
다음 사항만 알려줄 수 있습니다.유전학따라서 온전성 검사에 유용합니다.env -i
: 하위 프로세스를 시작하기 전에 환경을 정리하는 데 유용합니다.
대체 계획 export
:
name=val command
# 명령 앞에 할당하면 이름이 명령으로 내보내집니다.declare/local -x name
# 이름을 내보냅니다. 특히 이름이 외부 범위에 노출되는 것을 방지하려는 경우 쉘 함수에 유용합니다.set -a
# 다음 각 작업을 내보냅니다.
동기 부여
그렇다면 쉘에는 왜 자체적인 다른 변수와 환경이 필요한가요? 물론 몇 가지 역사적인 이유가 있을 거라 확신하지만, 주된 이유는 범위 지정 때문이라고 생각합니다. 이 환경은 하위 프로세스용이지만 하위 프로세스를 포크하지 않고도 셸에서 많은 작업을 수행할 수 있습니다. 루프를 반복한다고 가정해 보세요.
for i in {0..50}; do
somecommand
done
somecommand
을 포함하여 i
환경을 필요한 것보다 더 크게 만들어 메모리를 낭비하는 이유는 무엇입니까? 쉘에서 선택한 변수 이름이 프로그램이 의도하지 않은 것을 의미한다면 어떻게 될까요? (제가 개인적으로 가장 좋아하는 이름에는 DEBUG
. 및 가 있습니다 VERBOSE
. 이러한 이름은 어디에나 있지만 네임스페이스가 거의 없습니다.)
쉘이 아니라면 어떤 환경인가요?
때로는 Unix 동작을 이해하기 위해 커널 및 운영 체제와 상호 작용하기 위한 기본 API인 시스템 호출을 살펴봐야 합니다. 여기서는 exec
하위 프로세스를 생성할 때 쉘에서 사용되는 호출 시리즈를 살펴보겠습니다 . 이것은에서 온 것입니다맨페이지exec(3)
(강조):
execle()
함수를 사용하면execvpe()
호출자가 envp 매개변수를 통해 프로그램이 실행되는 환경을 지정할 수 있습니다. envp 매개변수는 NULL로 끝나는 문자열에 대한 포인터 배열이며 NULL 포인터로 끝나야 합니다.다른 함수는 호출 프로세스의 외부 변수environ에서 새 프로세스 이미지의 환경을 가져옵니다.
따라서 셸에 쓰는 것은 C의 전역 사전 export somename
에 이름을 복사하는 것과 같습니다 . environ
그러나 somename
내보내지 않고 할당하는 것은 C에서 변수에 복사하지 않고 할당하는 것과 같습니다 environ
.
답변2
쉘 변수와 환경 변수에는 차이가 있습니다. 셸 변수를 지정하지 않고 정의하면 export
해당 변수는 프로세스 환경에 추가되지 않으므로 해당 하위 프로세스에 상속되지 않습니다.
export
환경에 추가하도록 쉘에 지시한 쉘 변수를 사용하십시오 . 다음을 사용하여 테스트할 수 있습니다. printenv
(환경을 에 인쇄하고 stdout
하위 프로세스이므로 export
ing 변수의 효과를 볼 수 있습니다.)
#!/bin/sh
MYVAR="my cool variable"
echo "Without export:"
printenv | grep MYVAR
echo "With export:"
export MYVAR
printenv | grep MYVAR
답변3
변수를 내보내면 해당 변수는 환경의 일부가 됩니다. PATH
셸 자체에서 내보낼 수 있으며 필요에 따라 사용자 정의 변수를 내보낼 수 있습니다. 일부 설정 코드를 사용하십시오.
$ cat subshell.sh
#!/usr/bin/env bash
declare | grep -e '^PATH=' -e '^foo='
비교하다
$ cat test.sh
#!/usr/bin/env bash
export PATH=/bin
export foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test.sh
PATH=/bin
foo=bar
PATH=/bin
foo=bar
그리고
$ cat test2.sh
#!/usr/bin/env bash
PATH=/bin
foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test2.sh
PATH=/bin
foo=bar
PATH=/bin
foo
셸에서 내보낸 적이 없고 내 보낸 적이 없으므로 마지막 실행 환경의 일부 test2.sh
가 아닙니다 .subshell.sh
답변4
간단히 말해서:
- 프로세스는 상위 프로세스로부터 환경 변수를 상속받습니다.
- Bash에서 $a=1은 환경 변수가 아닌 "일반" 변수를 생성합니다.
- 내보내기 a=1은 터미널 프로세스에 대한 환경 변수를 생성합니다(다른 방법이 있음)
- 환경 데이터를 하위 프로세스에 전달하는 다른 방법이 있습니까?