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


425

当我对sudo使用任何命令时,环境变量不存在。例如,设置HTTP_PROXY后,wget如果不使用,该命令可以正常工作sudo。但是,如果我键入sudo wget它说它不能绕过代理设置。



Answers:


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
伟大的唯一问题是修改一些配置文件,例如pacman以使arch通过-E
Ahmed Aswani

7
要为wget允许-E(保留环境),您需要在允许运行wget的sudo规则上指定SETENV标记-例如:<username> ALL =(root)NOPASSWD:SETENV:<wget的路径>
John Bowers 2014年

65
如果变量是PATH或PYTHONPATH,则此“ -E”不起作用。
apporc

也不适用于任何LC_*变量。因此,只需export LOL_FOO=$LC_FOO使用即可LOL_FOO
luckydonald 2016年

9
这不适用于PATH.bashrc文件中向中添加一个元素这一较简单的情况-例如,export PATH=myPath:$PATH。如果键入sudo -E bash -c 'echo $PATH',则PATH可能不包含myPath,可能是因为sudoPATH在调用之前禁用了本地值bash。相反,我发现stackoverflow.com/a/33183620/5459638下面的答案有效,即sudo 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是一次即席获得肯定效果的一次性方法,不过
2011年

我遇到了一个进程问题,该进程是调用sudo(jhbuild)的进程,我无法告诉它将-E标志传递给sudo,所以这是我的解决方案。
jgomo3

60
请注意,您永远不要etc/sudoers直接编辑直接。而是使用visudo命令,该命令在覆盖sudoers文件之前先对您的编辑进行语法检查。这样,如果您在编辑时犯了错误,就不会把自己锁在门外。
亨宁

1
考虑使用大写的环境变量。就我而言,使用HTTP_PROXY和HTTPS_PROXY可以解决问题。
pabo

2
根据我的经验,小写字母变体更好,因为它既可以在wget中使用,也可以在curl中使用。
米罗斯拉夫·摩切克

57

对于要一次性使用的单个变量,可以使其成为命令的一部分。

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

我已经针对package添加到文件PATH中的某些myPath .bashrc(使用exportclausule)测试了此答案。然后sudo PATH=$PATH which package找到正确的答案,不像sudo which package。但是,sudo PATH=$PATH package除了sudo package(找不到文件)外,其他操作都没有。另一方面,package从使用调用的外壳启动平原会sudo bash保留扩展路径并赋予packagesudo权限(两只鸽子一块石头)。因此,响应的确取决于您要启动的命令
XavierStuvw

2
sudo的路径解析是另一回事-任何人都应该找到这个帖子里寻找这个问题我建议您检查一下unix.stackexchange.com/questions/83191/...
buckaroo1177125

24

您还可以将env_keep艾哈迈德·阿斯瓦尼(Ahmed 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" "$@" 就我而言很丑

演示

#!/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产生一个shell引号的字符串。与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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.