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

问题描述 投票:0回答:7

当我使用 sudo 的任何命令时,环境变量不存在。例如,设置

HTTP_PROXY
后,命令
wget
可以在没有
sudo
的情况下正常工作。但是,如果我输入
sudo wget
,它会说它无法绕过代理设置。

linux environment-variables sudo
7个回答
648
投票

首先您需要

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.

377
投票

技巧是通过

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"

91
投票

对于您想要一次性提供的单个变量,您可以将其作为命令的一部分。

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

27
投票

您还可以将 Ahmed Aswani 的答案中的两个

env_keep
语句合并为一个语句,如下所示:

Defaults env_keep += "http_proxy https_proxy"

您还应该考虑仅为单个命令指定

env_keep
,如下所示:

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


13
投票

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

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

  • sudo -E "$@"
    正在泄漏变量,导致我的命令出现问题
  • sudo VAR1="$VAR1" ... VAR42="$VAR42" "$@"
    对我来说又长又丑

演示.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
生成一个 shell 带引号的字符串。与 bash 4.4 中的参数扩展不同,这适用于 bash 版本 < 4.0


4
投票

不知道这是否在所有发行版中都可用,但在基于 Debian 的发行版中,在

/etc/sudoers

文件的尾部或附近有一行,其中包含文件夹

/etc/sudoers.d
。在此,可以
添加代码
“snippets”来修改 sudo 的配置。具体来说,它们允许控制sudo中使用的所有环境变量。

/etc/sudoers

一样,这些

“代码片段”
应使用 visudo 进行编辑。您可以从阅读
README
文件开始,这也是保存您想要做的任何笔记的方便位置:
$ sudo visudo -f /etc/sudoers.d/README 

# files for your snippets may be created/edited like so:

$ sudo visudo -f /etc/sudoers.d/20_mysnippets

阅读“man 5 sudoers”的“命令环境”部分

也许有关

sudo

中环境配置的信息最丰富的文档可以在

Command environment
man 5 sudoers
部分找到。在这里,我们了解到默认情况下阻止的
sudoers
环境变量可能是使用 env_checkenv_keep 选项的
“白名单”
;例如
Defaults env_keep += "http_proxy HTTP_PROXY"
Defaults env_keep += "https_proxy HTTPS_PROXY"
Defaults env_keep += "ftp_proxy FTP_PROXY"

因此,在OP的情况下,我们可以“传递”
sudoer的

环境变量,如下所示: $ sudo visudo -f /etc/sudoers.d/10_myenvwlist # opens the default editor for entry of the following lines: Defaults env_keep += "http_proxy HTTP_PROXY" Defaults env_keep += "https_proxy HTTPS_PROXY" # and any others deemed useful/necessary # Save the file, close the editor, and you are done!

从“# sudo -V”获取你的方位

OP 大概通过

反复试验

发现了

sudo
中缺失的环境变量。但是,可以采取主动措施:从 root 提示中可以获取所有环境变量及其允许或拒绝状态的列表(并且对于每个主机而言都是唯一的),如下所示:
# sudo -V
...
Environment variables to check for safety: 
...
Environment variables to remove: 
...
Environment variables to preserve:
...

请注意,一旦环境变量被如上所述列入“白名单”,它将出现在“保留”列表下的
sudo -V

的后续列表中。

    


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

© www.soinside.com 2019 - 2024. All rights reserved.