쉘 변수는 어떤 범위를 가질 수 있습니까?

쉘 변수의 범위가 명확하지 않다는 문제가 발생했습니다.

작업을 수행하기 위해 $GEM_HOME 값을 사용하는 Ruby 명령 인 bundle install를 사용합니다. ,하지만 export GEM_HOME=/some/path 에서처럼 export를 사용할 때까지 명령은 해당 값을 무시했습니다.

이로 인해 변수가 “전역”( 환경 변수 라고도 함)이 어떻게 든 “글로벌”이라는 것을 읽었지만 그것이 무엇을 의미하는지 이해하십시오. 프로그래밍에서 전역에 대해 알고 있지만 개별 프로그램에는 적용되지 않습니다.

또한 이러한 변수 설정이 현재 셸 세션에만 적용된다는 점을 감안할 때 데몬 화 된 프로세스에 대해 어떻게 설정해야합니까?

셸 변수는 어떤 범위를 가질 수 있습니까?

답변

프로세스는 트리로 구성됩니다. 모든 프로세스에는 init를 제외하고 PID는 항상 1이며 부모가 없습니다.

새 프로세스 생성은 일반적으로 fork / execv 시스템 호출. 여기서 하위 프로세스의 환경은 상위 프로세스의 복사 입니다.

셸에서 환경에 변수를 넣으려면 해당 변수를 export해야 모든 하위 항목이 재귀 적으로 볼 수 있습니다. 그러나 자식이 변수의 값을 변경하면 변경된 값은 해당 변수와 변경된 이후 에 생성 된 모든 프로세스 (이전과 같이 사본 이 됨)에만 표시됩니다.

예를 들어 login에서 수행 한 것처럼 하위 프로세스가 환경을 변경할 수 있다는 점도 고려하십시오. 예.

댓글

  • 아! 알겠습니다. ‘ 제가 이해하는지 확인해 보겠습니다. 셸에서 FOO=bar라고 말하면 현재 셸 프로세스의 값을 설정합니다. 그런 다음 (bundle install)와 같은 프로그램을 실행하면 하위 프로세스가 생성되어 ‘ FOO. 그러나 내가 export FOO=bar라고 말했다면 하위 프로세스 (및 그 하위 프로세스)가 액세스 할 수 있습니다 . 그 중 하나는 export FOO=buzz를 호출하여 하위 항목의 값을 변경하거나 FOO=buzz를 호출하여 자신의 값만 변경할 수 있습니다. . 그게 맞습니까?
  • @NathanLong 그 ‘ 정확히 아닙니다. 모든 최신 셸에서 변수가 내보내집니다 (따라서 값의 변경은 하위 환경에 반영됨) 또는 내 보내지 않음 (변수가 환경에 없음). 특히 셸이 시작될 때 변수가 이미 환경에 있으면 내보내집니다.
  • ” 문장에 약간 혼란 스러웠습니다. 변수의 값을 변경하면 변경된 값은 변수와 해당 변경 이후에 생성 된 모든 프로세스에만 표시됩니다 “. ” … 표시 및 변경 후 생성 된 모든 하위 프로세스 ” – 다른 하나에 표시되는 것이 더 정확합니다. 상위 프로세스의 하위 항목 (하위 프로세스 이후에 시작된 항목도 포함)은 영향을받지 않습니다.

Answer

At 최소한 kshbash에서 변수는 3 개 범위, 2 개의 나머지 모든 답변이 현재 말하고있는 것처럼

In 내 보낸 (예 : 환경) 변수 및 셸 내보내기되지 않은 변수 범위 외에도 함수 지역 변수에 대해 세 번째로 좁은 범위가 있습니다.

typeset 토큰은 선언 된 함수 내부와 거기에서 호출 된 (sub) 함수에서만 볼 수 있습니다.

ksh / bash 코드 :

# Create a shell script named /tmp/show that displays the scoped variables values. echo "echo [$environment] [$shell] [$local]" > /tmp/show chmod +x /tmp/show # Function local variable declaration function f { typeset local=three echo "in function": . /tmp/show } # Global variable declaration export environment=one # Unexported (i.e. local) variable declaration shell=two # Call the function that creates a function local variable and # display all three variable values from inside the function f # Display the three values from outside the function echo "in shell": . /tmp/show # Display the same values from a subshell echo "in subshell": /tmp/show # Display the same values from a disconnected shell (simulated here by a clean environment start) echo "in other shell" env -i /tmp/show 

이 출력을 생성합니다.

in function: [one] [two] [three] in shell: [one] [two] [] in subshell: [one] [] [] in other shell [] [] [] 

보시다시피 내 보낸 변수는 처음 세 위치에서 표시되고 내 보내지 않은 변수는 현재 셸 외부에 표시되지 않으며 함수 로컬 변수에는 함수 자체 외부에 값이 없습니다. 마지막 테스트에서는 값이 전혀 표시되지 않습니다. 이는 내 보낸 변수가 쉘간에 공유되지 않기 때문입니다. 즉, 상속 만 가능하고 상속 된 값은 나중에 상위 쉘에 의해 영향을받을 수 없기 때문입니다.

후자의 동작은 모든 프로세스에서 완전히 전역적이고 공유되는 시스템 변수를 사용할 수있는 Windows 동작과는 상당히 다릅니다.

답변

그들은 프로세스별로 범위가 지정됩니다.

다른 응답자들은 쉘 변수 범위가 프로세스에 관한 것이라는 것을 이해하는 데 도움이되었습니다. 및 그 하위 항목 .

명령 줄에 ls와 같은 명령을 입력하면 실제로 프로세스를 분기하여 ls 프로그램을 실행합니다. 새 프로세스에는 셸이 부모로 있습니다.

모든 프로세스는 자체 “로컬”변수를 가질 수 있습니다. 하위 프로세스에 전달되지 않습니다. “환경”변수를 설정할 수도 있습니다. export를 사용하면 환경 변수가 생성됩니다. 경우, 관련없는 프로세스 (원본의 동료)는 변수를 볼 수 없습니다. esses see.

A라고 부르는 bash 쉘이 있다고 가정합니다. bash를 입력합니다. , B라고 부르는 자식 프로세스 bash 셸을 만듭니다. A에서 export를 호출 한 모든 항목은 여전히 B로 설정됩니다.

이제, B에서는 FOO=b라고 말합니다. 다음 두 가지 중 하나가 발생합니다.

  • B가 (A로부터) FOO라는 환경 변수를받지 못한 경우 로컬 변수를 생성합니다. B의 하위 항목은 해당 정보를 얻지 못합니다 (B가 export를 호출하지 않는 한).
  • B가 인 경우 A로부터 FOO라는 환경 변수를 수신하면 자체를 위해 수정하고 그 후에 갈라진 아이들 . B의 자식은 B가 할당 한 값을 볼 수 있습니다. 그러나 A에는 전혀 영향을주지 않습니다.

다음은 빠른 데모입니다. .

FOO=a # set "local" environment variable echo $FOO # "a" bash # forks a child process for the new shell echo $FOO # not set exit # return to original shell echo $FOO # still "a" export FOO # make FOO an environment variable bash # fork a new "child" shell echo $FOO # outputs "a" FOO=b # modifies environment (not local) variable bash # fork "grandchild" shell echo $FOO # outputs "b" exit # back to child shell exit # back to original shell echo $FOO # outputs "a" 

이 모든 것이 내 원래 문제를 설명합니다. 쉘에 GEM_HOME를 설정했지만 bundle install, 하위 프로세스를 생성했습니다. export를 사용하지 않았기 때문에 하위 프로세스가 쉘의 GEM_HOME.

내보내기 취소

export -n FOO.

export FOO=a # Set environment variable bash # fork a shell echo $FOO # outputs "a" export -n FOO # remove environment var for children bash # fork a shell echo $FOO # Not set exit # back up a level echo $FOO # outputs "a" - still a local variable 

댓글

  • 말할 때 ” 자체 및 하위 항목을 위해 수정합니다. ” 수정 에 생성 된 하위 항목 만 명시해야합니다. 수정 된 값이 표시됩니다.
  • @enzotib-좋은 지적입니다. 업데이트되었습니다.

답변

내보내기에 대해 찾을 수있는 가장 좋은 설명은 다음과 같습니다.

http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_02.html

서브 쉘 또는 하위 쉘 내에 설정된 변수는 다음 사용자에게만 표시됩니다. 정의 된 서브 쉘. 내 보낸 변수는 실제로 환경 변수로 만들어집니다. 따라서 bundle install는 iv id = “42dce32f9e로 만들어지지 않는 한 $GEM_HOME를 볼 수없는 자체 셸을 실행합니다. “>

변수 (일명 내보냄)

여기에서 변수 범위에 대한 설명서를 볼 수 있습니다.

http://www.tldp.org/LDP/abs/html/subshells.html

댓글

  • 아, 그래서 ” 환경 변수 ” for FOO=bar; export로 만들었습니다. 그에 따라 질문이 수정되었습니다.
  • 추가 한 링크를 살펴보세요.

답변

예상대로 변수 범위의 계층 구조가 있습니다.

환경

가장 바깥 쪽 범위는 환경입니다. 이것이 유일한 범위입니다. 운영 체제에 의해 관리되므로 모든 프로세스에 대해 존재하도록 보장됩니다. 프로세스가 시작되면 부모의 환경을 복사 한 후 둘이 독립적이됩니다. 자식의 환경을 수정해도 부모의 환경은 바뀌지 않으며 부모의 환경을 수정해도 기존 자식의 환경은 바뀌지 않습니다.

쉘 변수

쉘에는 고유 한 변수 개념이 있습니다. 이것이 약간 혼란스러워지기 시작하는 부분입니다.

셸의 변수에 값을 할당하고 해당 변수가 환경에 이미 존재하면 환경 변수가 새 값을받습니다. 그러나 변수가 아직 환경에 없으면 shell 변수가됩니다. Ruby 변수가 Ruby 스크립트 내에서만 존재하는 것과 유사하게 쉘 변수는 쉘 프로세스 내에서만 존재합니다. 자식 프로세스에 상속되지 않습니다.

여기에서 export 키워드가 작동합니다. 셸 변수를 셸 프로세스의 환경에 복사하여 자식 프로세스가 상속 할 수 있도록합니다.

지역 변수

지역 변수는이를 포함하는 코드 블록으로 범위가 지정된 셸 변수입니다. typeset 키워드 (휴대용) 또는 local 또는 declare (배시 ). 다른 쉘 변수와 마찬가지로 지역 변수는 자식 프로세스에 상속되지 않습니다. 또한 지역 변수는 내보낼 수 없습니다.

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다