Bash 스크립트가 로컬 환경 변수 네임스페이스와 충돌합니다.

Bash 스크립트가 로컬 환경 변수 네임스페이스와 충돌합니다.

bash script라는 파일이 있습니다VAR_A

나도 현지 env variable이름이 있어VAR_A

호출 bash script명령:

echo ${VAR_A}

스크립트의 변수를 다른 이름으로 변경할 수는 없지만 스크립트가 명령을 호출하는 방식은 변경할 수 있습니다 echo.

스크립트에 제공된 명령 대신 echo로컬 명령을 인쇄하도록 명령을 수정하려면 어떻게 해야 합니까 ?env variable

UPDATE FOR CLARITY:

상태:

사용자에게 .bashrc로그인 시 설정된 기존 파일이 있습니다.

VAR_A="someValue"
export VAR_A

이를 통해 사용자는 다음을 수행할 수 있습니다.

~]$ echo ${VAR_A}
    someValue

Bash 스크립트에 대한 일부 구성 파일이 있습니다

VAR_A="someOtherValue"

Bash 스크립트가 있습니다.

#!/bin/bash

. ../configuration  # imports config file with some values

#  do stuff

echo ${VAR_A}

터미널(로그인한 사용자로 bash 쉘)에서 스크립트를 실행하면 다음이 인쇄됩니다.

~]$ ./run_script.sh
    someOtherStuff

인쇄하려면 다음이 필요합니다.

~]$ ./run_script.sh
    someStuff

답변1

셸 변수는 각 셸의 환경 변수에서 초기화되므로 이 문제를 해결할 수 없습니다.

쉘이 시작되면 유효한 이름의 쉘 변수로 수신되는 각 환경 변수에 대해 쉘은 해당 쉘 변수에 적절한 값을 지정합니다. 예를 들어 스크립트가 다음과 같이 시작하는 경우:

env VAR_A=xxx your-script

(그리고 she-bang이 있습니다 #!/bin/bash -)이 env실행되어 해당 bash 명령에 /bin/bash전달되고 해당 변수에 값이 할당됩니다 .VAR_A=xxxbash$VAR_Axxx

Bourne 쉘 및 C-쉘에서 쉘 변수에 새 값을 할당하면 이후에 쉘에서 실행되는 명령에 전달되는 해당 환경 변수에 영향을 미치지 않습니다. 이를 달성하려면 export또는 를 사용해야 합니다. setenvBourne 쉘에서는 unset변수를 사용하면 쉘 변수와 환경 변수가 제거됩니다.

존재하다:

env VAR=xxx sh -c 'VAR=yyy; other-command'

( sh현대 POSIX 쉘이 아닌 Bourne 쉘) 또는:

env VAR=xxx csh -c 'set VAR = yyy; other-command'

other-commandVAR=xxx해당 환경에서 이를 받으려면 대신 VAR=yyy다음과 같이 작성해야 합니다.

env VAR=xxx sh -c 'VAR=yyy; export VAR; other-command'

또는

env VAR=yyy csh -c 'setenv VAR yyy; other-command'

해당 환경에서 수신됩니다 other-command.VAR=yyy

그러나 (POSIX와 다른 모든 현대 Bourne 유사 쉘이 ksh밝혀진 것처럼 ) 이 문제가 발생했습니다.bash

시작 시 최신 쉘제본해당 환경 변수에 쉘 변수를 추가하십시오.

이는 변수를 내보내지 않더라도 스크립트가 변수 중 하나를 설정하는 것만으로도 환경을 손상시킬 수 있음을 의미합니다. 일부 쉘은 쉘 변수에 매핑할 수 없는 환경 변수도 제거합니다. 따라서 쉘 매핑 가능한 변수 이름만 환경 변수 이름으로 사용하는 것이 좋습니다.

이것이 관례에 따라 모든 대문자 변수가 환경 변수용으로 예약되어야 하는 주된 이유입니다.

이 문제를 해결하려면 스크립트에 의해 실행되는 명령이 스크립트를 해석하는 셸과 동일한 환경을 수신하도록 하려면 어떻게든 해당 환경을 저장해야 합니다. 다음을 추가하면 됩니다.

my_saved_env=$(export -p)

스크립트 시작 부분에 다음을 사용하여 명령을 실행합니다.

(eval "$my_saved_env"; exec my-other-command and its args)

껍질 boshmksh껍질,현지의함수의 변수는 환경 변수를 파괴하지 않습니다(환경 변수를 파괴하지 않는 한 ). 그러나 일부 특수 변수(예 : 실행 가능한 조회를 위한 for , ...) export를 사용하는 셸 내장 기능은 다음을 사용합니다.HOMEcdPATH껍데기(로컬) 변수, 환경 변수가 아닙니다.

$ env VAR=env mksh -c 'f() { local VAR=local; echo "$VAR"; printenv VAR; }; f'
local
env

답변2

VAR_A다음 줄을 추가하여 변수를 읽기 전용으로 만들 수 있습니다.

readonly VAR_A

스크립트 상단에 있습니다. 그러면 VAR_A다음과 같은 값이 발생합니다 .예약하다지역 환경에 따라 다릅니다.

readonly: readonly [-aAf] [name[=value] ...] or readonly -p

Mark shell variables as unchangeable.

Mark each NAME as read-only; the values of these NAMEs may not be
changed by subsequent assignment.  If VALUE is supplied, assign VALUE
before marking as read-only.

Options:
  -a        refer to indexed array variables
  -A        refer to associative array variables
  -f        refer to shell functions
  -p        display a list of all readonly variables and functions

An argument of `--' disables further option processing.

Exit Status:
Returns success unless an invalid option is given or NAME is invalid.

다음 예를 보면 명확해집니다.

$ export FOO="somevalue"        # environment variable FOO set to somevalue
$ cat test                      # test script
echo $FOO                       # print the value of FOO
readonly FOO                       # set FOO to local
FOO="something"                 # attempt to modify FOO
echo $FOO                       # print the value of FOO -- you would see the value that was inherited from the environment
$ bash test
somevalue
test: line 3: FOO: readonly variable
something

답변3

인쇄하고 싶다면현지의Variable 은 VAR_A로컬 범위에서 호출해야 합니다. 그렇지 않으면 전역 변수의 값을 인쇄합니다 VAR_A.

#! /bin/bash 

VAR_A="I'm global"

function lexical() {
    local VAR_A="I'm lexical"
    echo $VAR_A
}

echo -n "Global VAR_A: "
echo $VAR_A
echo -n "Lexical VAR_A: "
lexical

달리다:

$ ./test.sh 
Global VAR_A: I'm global
Lexical VAR_A: I'm lexical

local다음 페이지에서 bash에 대한 자세한 내용을 읽을 수 있습니다 man.

local [option] [name[=value] ...]
              For each argument, a local variable named name is  created,  and
              assigned  value.   The option can be any of the options accepted
              by declare.  When local is used within a function, it causes the
              variable  name  to have a visible scope restricted to that func‐
              tion and its children.  With no operands, local writes a list of
              local  variables  to the standard output.  It is an error to use
              local when not within a function.  The return status is 0 unless
              local  is  used outside a function, an invalid name is supplied,
              or name is a readonly variable.

답변4

VAR_A무슨 일이 일어나고 있는지 구성 파일 VAR_A.bashrc.

따라서 해결 방법 자체는 다음과 같습니다. 구성 파일을 가져오기 전에 VAR_A아래와 같이 내용을 저장하세요.

VAR_A_sav=${VAR_A} # assuming that VAR_A_sav does NOT exist in configuration

. ../configuration # that is, you must choose a name not existing in config.

VAR_A=${VAR_A_sav}

관련 정보