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'

これはmanページからの引用です:

-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が渡されるように、archのpacmanなどのいくつかの設定ファイルを変更することです
Ahmed Aswani

7
wgetに-E(環境の維持)を許可するには、wgetの実行を許可するsudoルールでSETENVタグを指定する必要があります-例:<username> ALL =(root)NOPASSWD:SETENV:<path to wget>
ジョンバウアーズ

66
変数がPATHまたはPYTHONPATHの場合、この「-E」は機能しません。
apporc 2016年

また、どのLC_*変数でも機能しません。ですからexport LOL_FOO=$LC_FOOLOL_FOO代わりに使用してください。
ラッキードナルド2016年

9
これはPATH.bashrcファイル内の1つの要素を追加するという単純なケースでは機能しませんでしたexport PATH=myPath:$PATH。と入力するとsudo -E bash -c 'echo $PATH'PATHmyPathが含まれていません。おそらく、呼び出す前にのsudoローカル値がすでに無効になっているためです。むしろ、私はstackoverflow.com/a/33183620/5459638の下の答えが効果的であることを発見しました、つまり、PATHbashsudo PATH=$PATH command
XavierStuvw

310

トリックは、コマンドをsudoers使用してファイルに環境変数をsudo visudo追加し、次の行を追加することです。

Defaults env_keep += "ftp_proxy http_proxy https_proxy no_proxy"

ArchLinux wikiから取得

Ubuntu 14の場合、多変数行のエラーを返すため、別の行で指定する必要があります。

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

11
これはおそらく、情報漏えいやセキュリティホールを回避するための最良の選択肢です。sudo -Eアドホックに確実に同じ方法で1回限りの効果を得る方法です
sehe

プロセスがsudo(jhbuild)を呼び出すプロセスであるという問題に遭遇し、-Eフラグをsudoに渡すように指示することができないため、これが私の解決策です。
jgomo3 2013年

61
決して編集しないでくださいetc/sudoers直接。代わりに、ファイルをvisudo上書きする前に編集内容を構文チェックするコマンドを使用しsudoersます。そうすれば、編集中に間違えてもロックアウトされません。
ヘニング

1
大文字のenv変数の使用を検討してください。私の場合、HTTP_PROXYとHTTPS_PROXYの使用でうまくいきました。
パボ2015

2
小文字のバリアントは、wgetとcurlの両方で機能するため、私の経験からはより優れています。
Miroslav Mocek 2015年

57

個別に使用できるようにする個々の変数については、コマンドの一部にすることができます。

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

私はこの回答をファイルにpackage追加さPATHれたmyPathの下でテストしました.bashrcexport節を含む)。次にsudo PATH=$PATH which package、とは異なり、正しい答えを見つけsudo which packageます。ただし、(ファイルが見つからない)sudo PATH=$PATH packageより先に進むことはありませんsudo package。一方、でpackage呼び出されたシェルからプレーンを起動するとsudo bash、拡張パスが保持され、packagesudo権限が付与されます(1つの石で2つのハト)。したがって、応答は実際に起動しているコマンドによって異なります
XavierStuvw

2
誰もが私が見て示唆している物質の検索でこのポストを見つけなければならない- sudoのためのPATH解像度は別の問題ですunix.stackexchange.com/questions/83191/...を
buckaroo1177125

24

env_keepAhmed Aswaniの回答の2つのステートメントを次のような1 つのステートメントに結合することもできます。

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

スクリプトに環境変数を保持する必要がある場合は、このようなhereドキュメントにコマンドを配置できます。特に、設定する変数がたくさんある場合は、この方法で整然と見えます。

# 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.