Linux 使用sudo时如何保留环境变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8633461/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 03:49:20  来源:igfitidea点击:

How to keep environment variables when using sudo

linuxenvironment-variablessudo

提问by Ahmed Aswani

When I use any command with sudo the environment variables are not there. For example after setting HTTP_PROXY the command wgetworks fine without sudo. However if I type sudo wgetit says it can't bypass the proxy setting.

当我对 sudo 使用任何命令时,环境变量不存在。例如,在设置 HTTP_PROXY 后,该命令在wget没有sudo. 但是,如果我输入sudo wget它说它不能绕过代理设置。

采纳答案by Ahmed Aswani

The trick is to add environment variables to sudoersfile via sudo visudocommand and add these lines:

诀窍是sudoers通过sudo visudo命令将环境变量添加到文件并添加以下行:

Defaults env_keep += "ftp_proxy http_proxy https_proxy no_proxy"

taken from ArchLinux wiki.

取自ArchLinux 维基

For Ubuntu 14, you need to specify in separate lines as it returns the errors for multi-variable lines:

对于 Ubuntu 14,您需要在单独的行中指定,因为它返回多变量行的错误:

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

回答by Employed Russian

First you need to export HTTP_PROXY. Second, you need to read man sudocarefully, and pay attention to the -Eflag. This works:

首先你需要export HTTP_PROXY。其次,你需要man sudo仔细阅读,并注意-E标志。这有效:

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

Here is the quote from the man page:

这是手册页的引用:

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

回答by Stian S

You can also combine the two env_keepstatements in Ahmed Aswani's answer into a single statement like this:

您还可以将env_keep艾哈迈德·阿斯瓦尼 (Ahmed Aswani) 的回答中的两个语句组合成一个语句,如下所示:

Defaults env_keep += "http_proxy https_proxy"

Defaults env_keep += "http_proxy https_proxy"

You should also consider specifying env_keepfor only a single command like this:

您还应该考虑env_keep仅指定一个命令,如下所示:

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

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

回答by buckaroo1177125

For individual variables you want to make available on a one off basis you can make it part of the command.

对于您希望一次性使用的单个变量,您可以将其作为命令的一部分。

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

回答by Wolfgang Fahl

If you have the need to keep the environment variables in a script you can put your command in a here document like this. Especially if you have lots of variables to set things look tidy this way.

如果您需要将环境变量保存在脚本中,您可以将您的命令放在像这样的 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

回答by Bruno Bronosky

A simple wrapper function (or in-line for loop)

一个简单的包装函数(或内联 for 循环)

I came up with a unique solution because:

我想出了一个独特的解决方案,因为:

  • sudo -E "$@"was leaking variables that was causing problems for my command
  • sudo VAR1="$VAR1" ... VAR42="$VAR42" "$@"was long and ugly in my case
  • 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

Result

结果

$ ./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.

How?

如何?

This is made possible by a feature of the bash builtin printf. The %qproduces a shell quoted string. Unlike the parameter expansion in bash 4.4, this works in bash versions < 4.0

这是通过 bash 内置功能实现的printf。将%q产生一个shell引号的字符串。与bash 4.4 中的参数扩展不同,这适用于 bash 版本 < 4.0