sudo를 사용할 때 환경 변수를 유지하는 방법


425

sudo와 함께 명령을 사용할 때 환경 변수가 없습니다. 예를 들어, HTTP_PROXY를 설정 한 후이 명령 wget은없이 작동합니다 sudo. 그러나 입력 sudo wget하면 프록시 설정을 무시할 수 없습니다.



답변:


475

먼저해야합니다 export HTTP_PROXY. 둘째, man sudo주의 깊게 읽고 -E깃발에 주의를 기울여야합니다 . 이것은 작동합니다 :

$ export HTTP_PROXY=foof
$ sudo -E bash -c 'echo $HTTP_PROXY'

맨 페이지의 인용문은 다음과 같습니다.

-E, --preserve-env
             Indicates to the security policy that the user wishes to preserve their
             existing environment variables.  The security policy may return an error
             if the user does not have permission to preserve the environment.

1
큰 - E는 통과되어 있는지 확인하는 아치에 대한 예를 들어, 팩맨에 대한 몇 가지 설정 파일을 수정하는 유일한 문제
아메드 Aswani

7
wget에 -E (환경 보존)를 허용하려면 wget 실행을 허용하는 sudo 규칙에 SETENV 태그를 지정해야합니다. 예 : <username> ALL = (root) NOPASSWD : SETENV : <wget 경로>
John Bowers

66
변수가 PATH 또는 PYTHONPATH 인 경우이 "-E"가 작동하지 않습니다.
apporc 2016 년

또한 LC_*변수 와 함께 작동하지 않습니다 . 그러니 그냥 이렇게 export LOL_FOO=$LC_FOO하고 사용 LOL_FOO하는 대신.
luckydonald

9
파일 PATH에 하나의 요소를 추가하는 간단한 경우에는 작동하지 않습니다 . 내가 입력하면 , 다음 있기 때문에 아마 MYPATH를 포함하지 않는 이미의 로컬 값을 사용할 수있다 호출하기 전에 . 오히려 stackoverflow.com/a/33183620/5459638 아래의 답변이 효과적이라는 것을 .bashrcexport PATH=myPath:$PATHsudo -E bash -c 'echo $PATH'PATHsudoPATHbashsudo PATH=$PATH command
알았습니다.

310

비결은 명령을 sudoers통해 파일 에 환경 변수를 sudo visudo추가하고 다음 줄을 추가하는 것입니다.

Defaults env_keep += "ftp_proxy http_proxy https_proxy no_proxy"

ArchLinux 위키 에서 가져온 것입니다 .

Ubuntu 14의 경우 다중 변수 행에 대한 오류를 반환하므로 별도의 행으로 지정해야합니다.

Defaults  env_keep += "http_proxy"
Defaults  env_keep += "https_proxy"
Defaults  env_keep += "HTTP_PROXY"
Defaults  env_keep += "HTTPS_PROXY"

11
정보 유출 및 보안 허점을 피하기위한 최선의 선택 일 것입니다. sudo -Eadhoc에 대한 확실한 방법은 일회성에 대해 동일한 효과를 얻을 수 있습니다.
sehe

sudo (jhbuild)를 호출하는 프로세스의 프로세스 문제가 발생하여 -E 플래그를 sudo에 전달하도록 지시 할 수 없으므로 이것이 내 솔루션입니다.
jgomo3

61
직접 편집 해서는 안됩니다etc/sudoers . 대신, 파일을 visudo덮어 쓰기 전에 편집 내용을 구문 검사 하는 명령을 사용 sudoers하십시오. 그렇게하면 편집 중에 실수를하더라도 자신을 잠그지 않습니다.
Henning

1
대문자 env vars 사용을 고려하십시오. 필자의 경우 HTTP_PROXY 및 HTTPS_PROXY를 사용하여 트릭을 수행했습니다.
pabo

2
소문자 변형은 wget과 curl 모두에서 작동하므로 내 경험에서 더 좋습니다.
Miroslav Mocek 2016 년

57

개별 변수에 대해 하나씩 사용 가능하게하려면 명령의 일부로 만들 수 있습니다.

sudo http_proxy=$http_proxy wget "http://stackoverflow.com"

나는이 대답을 테스트 한 package추가 일부 MYPATH에서 PATH.bashrc(와 파일 exportclausule). 그런 다음 sudo PATH=$PATH which package과 달리 정답을 찾습니다 sudo which package. 그러나 (파일을 찾을 수 없음) sudo PATH=$PATH package이상으로 가지 sudo package않습니다. 다른 한편으로, package호출 sudo bash된 껍질에서 평원 을 시작 하면 확장 된 경로 를 유지하고 packagesudo 권한을 부여합니다 (한 개의 돌을 가진 두 마리의 비둘기). 따라서 응답은 실제로 어떤 명령을 시작하는지에 따라 다릅니다.
XavierStuvw

2
sudo를위한 PATH 해상도는 또 다른 문제이다 - 누군가가 내가 보는 것이 좋습니다 그 문제의 검색이 게시물을 찾아야한다 unix.stackexchange.com/questions/83191/...
buckaroo1177125

24

env_keepAhmed Aswani의 답변에있는 두 가지 진술을 다음과 같은 단일 진술로 결합 할 수도 있습니다 .

Defaults env_keep += "http_proxy https_proxy"

다음 env_keep과 같은 단일 명령 만 지정하는 것도 고려해야 합니다.

Defaults!/bin/[your_command] env_keep += "http_proxy https_proxy"


1

간단한 래퍼 함수 (또는 인라인 for 루프)

나는 다음과 같은 이유로 독특한 솔루션을 생각해 냈습니다.

  • sudo -E "$@" 내 명령에 문제를 일으키는 변수가 누출되었습니다.
  • sudo VAR1="$VAR1" ... VAR42="$VAR42" "$@" 내 경우에는 길고 못생긴

demo.sh

#!/bin/bash

function sudo_exports(){
    eval sudo $(for x in $_EXPORTS; do printf '%q=%q ' "$x" "${!x}"; done;) "$@"
}

# create a test script to call as sudo
echo 'echo Forty-Two is $VAR42' > sudo_test.sh
chmod +x sudo_test.sh

export VAR42="The Answer to the Ultimate Question of Life, The Universe, and Everything."

export _EXPORTS="_EXPORTS VAR1 VAR2 VAR3 VAR4 VAR5 VAR6 VAR7 VAR8 VAR9 VAR10 VAR11 VAR12 VAR13 VAR14 VAR15 VAR16 VAR17 VAR18 VAR19 VAR20 VAR21 VAR22 VAR23 VAR24 VAR25 VAR26 VAR27 VAR28 VAR29 VAR30 VAR31 VAR32 VAR33 VAR34 VAR35 VAR36 VAR37 VAR38 VAR39 VAR40 VAR41 VAR42"

# clean function style
sudo_exports ./sudo_test.sh

# or just use the content of the function
eval sudo $(for x in $_EXPORTS; do printf '%q=%q ' "$x" "${!x}"; done;) ./sudo_test.sh

결과

$ ./demo.sh
Forty-Two is The Answer to the Ultimate Question of Life, The Universe, and Everything.
Forty-Two is The Answer to the Ultimate Question of Life, The Universe, and Everything.

어떻게?

이것은 bash 내장 기능으로 가능합니다 printf. 는 %q쉘 인용 문자열을 생성합니다. bash 4.4의 매개 변수 확장 과 달리 이것은 bash 버전 <4.0에서 작동합니다.


0

환경 변수를 스크립트에 보관해야 할 경우 여기에 문서에 명령을 넣을 수 있습니다. 특히 설정할 변수가 많으면 깔끔하게 보입니다.

# prepare a script e.g. for running maven
runmaven=/tmp/runmaven$$
# create the script with a here document 
cat << EOF > $runmaven
#!/bin/bash
# run the maven clean with environment variables set
export ANT_HOME=/usr/share/ant
export MAKEFLAGS=-j4
mvn clean install
EOF
# make the script executable
chmod +x $runmaven
# run it
sudo $runmaven
# remove it or comment out to keep
rm $runmaven
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.