Bash 및 Bourne Shell에서 명령 동작 내보내기

Bash 및 Bourne Shell에서 명령 동작 내보내기

bash v3.2 (최신 버전에서도 작동한다고 생각하지만):

3.7.4 환경 섹션의 설명서에는 다음과 같이 나와 있습니다.

호출되면 쉘은 환경을 스캔하고 발견된 각 이름에 대한 인수를 생성하여 자동으로 하위 프로세스로 내보낼 수 있도록 표시합니다.

나중에 부록 B Bourne Shell과의 주요 차이점에서 설명서에 다음과 같이 나와 있습니다.

쉘의 초기 환경에 있는 변수는 자동으로 하위 프로세스로 내보내집니다. Bourne 쉘은 일반적으로 내보내기 명령을 사용하여 변수를 명시적으로 표시하지 않는 한 이 작업을 수행하지 않습니다.

이것이 무엇을 의미하는지 이해하지 못합니다.

다음을 cmd1.sh포함하여

#!/bin/bash

echo yes $ben from cmd1
./cmd2.sh

그리고 cmd2.sh포함하다

#!/bin/bash

echo yes $ben from cmd2

나는 처음에 문서의 의미를 이해했습니다.모두할당된 변수가 내보내집니다(즉, export변수가 필요하지 않음). 즉, 런타임

ben=you;
./cmd1.sh

나는 이것이 인쇄될 것이라고 예상했다

yes you from cmd1
yes you from cmd2

하지만 대신 인쇄됩니다.

yes from cmd1
yes from cmd2

따라서 변수가 ben자동으로 내보내지지 않는 것 같습니다. 그렇다면 나는 문서가 모든 것을 의미할 것이라고 생각했습니다환경변수가 내보내집니다(예: 런타임).

ben=you;
export ben;
./cmd1.sh

cmd1은 환경 변수를 수신하므로 bencmd2 ben에서 볼 수 있도록 자동으로 내보내집니다. 즉, 다음이 인쇄될 것으로 예상했습니다(실제로는 다음이 인쇄되었습니다).

yes you from cmd1
yes you from cmd2

그러나 이것이 Bourne 쉘과 다른지 테스트하기 위해 (문서에 나와 있듯이) 똑같은 명령을 실행했지만 /bin/sh대신 을 가리키도록 shebang을 변경했으며 /bin/bash똑같은 결과를 얻었습니다. 즉, 아무런 차이가 없습니다. Bourne 쉘에서는 다음과 유사한 출력이 나올 것으로 예상됩니다.

yes you from cmd1
yes from cmd2

내보내기 매개변수를 "자동으로" 표시하는 것에 대해 이야기할 때 문서에서 말하는 내용과 이것이 Bourne 쉘과 어떻게 다른지 이해하도록 도와줄 수 있는 사람이 있습니까?

아뇨 알아냈어요이것bash 와 bourne 의 동작 사이의 구체적인 차이점에 대한 질문이 있지만 export관련성이 없는 것 같습니다.

답변1

"쉘의 초기 환경에 존재하는 변수는 자동으로 하위 프로세스로 내보내집니다. Bourne 쉘은 내보내기 명령을 사용하여 변수가 명시적으로 표시되지 않는 한 일반적으로 이 작업을 수행하지 않습니다."

고려하다:

% export FOO=abc
% bash -c 'FOO=xyz; echo "bash: FOO=$FOO"; echo "env:"; env |grep FOO'
bash: FOO=xyz
env:
FOO=xyz

FOO여기서는 대화형 셸 (zsh, 하지만 중요하지 않음) 에서 설정 하고 내보내도록 설정했습니다. 그런 다음 환경에서 변수를 수신하고 해당 값을 변경하고 인쇄한 다음 실행하는 Bash를 실행합니다 env. 이는 외부 명령이므로 명시적으로 전달된 내부 Bash 변수만 볼 수 있습니다. 우리가 보는 수정된 값은 FOOBash 내부에서 볼 수 있으므로 envBash는 환경에서 변수를 가져와서 내보낸 변수처럼 전달했습니다.

인용문에서 설명하는 또 다른 동작은 내부 쉘이 변수를 에 전달하지 않는다는 것입니다 env. 다음과 같은 내용이 표시됩니다.

bash: FOO=xyz
env:

모든 역사적 구현의 실제 동작이 무엇인지 모르겠습니다. 재현할 수 있는 것은 heirloom-sh(Kusalananda가 언급한 것과 동일한 동작)를 사용하는 것뿐입니다.원래변수 값이 전달됩니다.

% ./heirloom-sh -c 'FOO=xyz; echo "sh: FOO=$FOO"; echo "env:"; env |grep FOO'
sh: FOO=xyz
env:
FOO=abc

명시적인 export FOO내부 쉘도 현재 값을 전달합니다. 여기서 쉘은 원래 값을 FOO스크립트에 표시 하므로 echo "FOO=$FOO"첫 번째 값도 인쇄됩니다 FOO=abc.

답변2

원래 Bourne 쉘을 사용하지 않으므로 Bourne 쉘 동작이 나타날 것으로 예상하지 않습니다. POSIX sh셸(시스템에서 POSIX 모드로 실행되는 하나 이상의 다른 셸로 구현됨 bash)은 동일하게 동작하며 환경 변수와 관련하여 Bourne 셸 동작이 없습니다.dashbash

와 같은 POSIX 셸 sh과 오늘날 Unix의 다른 대부분의 일반적인 셸에서 셸이 셸의 상위 프로세스에서 상속하는 환경 변수는 셸에서 시작한 모든 하위 프로세스에 전달됩니다. 부록의 텍스트에서는 이를 "하위 프로세스로 자동으로 내보낸" 환경 변수라고 합니다.bashdash

부록에서는 이것이 원래 Bourne 셸의 경우가 아니며 하위 프로세스에서 상속한 환경 변수는 export상위 환경 또는 원래 셸에서 상속되었는지 여부에 관계없이 명령을 사용하여 명시적으로 내보내야 한다고 주장합니다. 에서 생성되었습니다.

내가 아는 한, 원래 Bourne 쉘에 가장 가까운 쉘은 다음과 같습니다./usr/sunos/bin/sh솔라리스에서. 이것코드베이스에 관한 한 실제로는 원래 Bourne 셸이지만 수년에 걸쳐 일부 업데이트가 있었을 수 있습니다.

설명서에 따르면 이 쉘은 설명서 부록에 설명된 대로 작동하지 않습니다 bash. 그것하다상속된 환경 변수를 하위 프로세스에 전달합니다. 그러나 상속된 환경 변수를 수정하려면 하위 프로세스에서 변경된 값을 볼 수 있도록 해당 변수를 내보내야 합니다.

[...] 호출되면 쉘은 환경을 스캔하고 발견된 각 이름에 대한 인수를 생성하여 적절한 값을 제공합니다.사용자가 이러한 매개변수의 값을 수정하거나 새 매개변수를 작성하는 경우 export명령이 셸의 매개변수를 환경에 바인딩하는 데 사용되지 않는 한 이러한 매개변수는 환경에 영향을 주지 않습니다.(또한 살펴보십시오 set –a). 이 명령을 사용하여 환경에서 매개변수를 제거할 수 있습니다 unset. 따라서 실행된 명령에 표시되는 환경은 원래 셸에서 상속된 수정되지 않은 이름-값 쌍에서 삭제된 쌍을 뺀 값으로 구성됩니다 unset.그리고 수정이나 추가 사항이 있으면 모두 export주문서에 기재 해야 합니다..

답변3

내보내지 않은 변수는 하위 프로세스의 환경에 없습니다. 이는 서브쉘을 실행할 때 서브쉘이 쉘의 초기 환경에 있지 않음을 의미합니다.

"쉘의 초기 환경에 존재하는 변수는 자동으로 하위 프로세스로 내보내집니다."는 정확하지만 변수가 환경에 아직 존재하지 않는 경우 해당 셸에서 사용할 수 없거나 하위 셸의 하위로 다시 내보낼 수 없습니다.

이는 내보내지 않은 쉘 변수와 내보낸 환경 변수 사이의 차이입니다. 쉘 변수는 현재 쉘에 대해 로컬이며 내보낸 변수는 현재 쉘(또는 다른 프로그램) 및 해당 서브루틴에서 볼 수 있습니다.

또한 주목할 만한 점은 자식 프로세스는 부모 프로세스의 환경을 변경할 수 없다는 것입니다. 따라서 자식 프로세스에서 환경 변수를 변경해도 부모 프로세스에는 아무런 영향이 없습니다.

관련 정보