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

Linux 使用sudo时如何保持环境变量,linux,environment-variables,sudo,Linux,Environment Variables,Sudo,当我对sudo使用任何命令时,环境变量都不存在。例如,在设置HTTP_代理之后,命令wget在没有sudo的情况下可以正常工作。但是,如果我键入sudo wget它会说它不能绕过代理设置。首先需要导出HTTP\u代理。第二,您需要仔细阅读mansudo,并注意-E标志。这项工作: $ export HTTP_PROXY=foof $ sudo -E bash -c 'echo $HTTP_PROXY' 以下是手册页中的引用: -E, --preserve-env In

当我对sudo使用任何命令时,环境变量都不存在。例如,在设置HTTP_代理之后,命令
wget
在没有
sudo
的情况下可以正常工作。但是,如果我键入
sudo wget
它会说它不能绕过代理设置。

首先需要
导出HTTP\u代理。第二,您需要仔细阅读
mansudo
,并注意
-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.

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

Defaults env_keep += "ftp_proxy http_proxy https_proxy no_proxy"
摘自

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

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

您还可以将Ahmed Aswani答案中的两个
env_keep
语句组合成一个单独的语句,如下所示:

Defaults env\u keep+=“http\u proxy https\u proxy”

您还应该考虑只指定一个这样的命令:<代码> EnvyReest:


默认值/bin/[your_command]env_keep+=“http_proxy https_proxy”

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

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

如果需要将环境变量保存在脚本中,可以将命令放在这样的here文档中。特别是如果你有很多变量来设置,事情看起来就这么简单了

#准备脚本,例如用于运行maven的脚本
runmaven=/tmp/runmaven$$
#使用here文档创建脚本
猫$runmaven
#!/bin/bash
#在设置环境变量的情况下运行maven clean
导出ANT_HOME=/usr/share/ANT
导出MAKEFLAGS=-j4
mvn清洁安装
EOF
#使脚本可执行
chmod+x$runmaven
#运行它
sudo$runmaven
#将其删除或注释掉以保留
rm$runmaven
一个简单的包装函数(或内联for循环) 我提出了一个独特的解决方案,因为:

  • sudo-E“$@”
    正在泄漏导致我的命令出现问题的变量
  • sudo VAR1=“$VAR1”。。。VAR42=“$VAR42”“$@”
    在我的例子中又长又丑
demo.sh
#/bin/bash
函数sudo_exports(){
eval sudo$(对于$\u导出中的x;执行printf'%q=%q'$x”“${!x}”;完成;)“$@”
}
#创建一个作为sudo调用的测试脚本
echo'echo四十二是$VAR42'>sudo_test.sh
chmod+x sudo_test.sh
export VAR42=“生命、宇宙和一切终极问题的答案。”
export(导出)=“(导出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 VAR35 VAR36 VAR38 VAR39 VAR41 VAR42”
#干净的功能风格
sudo_导出。/sudo_test.sh
#或者只使用函数的内容
eval sudo$(对于$\u导出中的x;执行printf“%q=%q'”$x“${!x}”;完成;)/sudo\u test.sh
结果 怎么用?
这是由bash内置的printf
特性实现的。
%q
生成一个带shell引号的字符串。与之不同,这在bash版本<4.0

great中有效唯一的问题是修改一些配置文件,例如pacman for arch,以使-E被传递为wget允许-E(保留环境),您需要在sudo规则上指定允许运行wget的SETENV标记——例如:ALL=(root)NOPASSWD:SETENV:this“-E”如果变量是PATH或PYTHONPATH,则不起作用。也不适用于任何
LC.*
变量。因此,只需执行导出LOL\u FOO=$LC\u FOO
并使用
LOL\u FOO
即可。这不适用于在
.bashrc
文件的
路径中添加一个元素的简单情况,例如,
export PATH=myPath:$PATH
。如果我键入
sudo-ebash-c'echo$PATH'
,则
PATH
不包含myPath,可能是因为
sudo
在调用
bash
之前已经禁用了
PATH
的本地值。相反,我发现下面的答案是有效的,即
sudo PATH=$PATH command
这可以说是避免信息泄漏和安全漏洞的最佳选择
sudo-E
是一次性获得相同效果的可靠方法,尽管我遇到了调用sudo(jhbuild)的进程的问题,但我无法告诉它将-E标志传递给sudo,所以这是我的解决方案。请注意,永远不要直接编辑
etc/sudoers
。相反,请使用
visudo
命令,该命令在覆盖
sudoers
文件之前检查您的编辑。这样,如果你在编辑过程中出错,你不会把自己锁在外面。考虑使用大写EVV VARS。在我的例子中,HTTP_代理和HTTPS_代理的使用起到了作用。根据我的经验,小写变量更好,因为它在wget和curl中都能工作。相关:在Unix上,SEI在
.bashrc
文件(带有
导出
子句)中添加到
路径
的一些myPath下测试了这个答案。然后
sudo PATH=$PATH which package
找到正确答案,这与
sudo which package
不同。但是,
sudo-PATH=$PATH-package
不会超过
sudo-package
(未找到文件)。另一方面,从使用
sudobash
调用的shell启动一个普通的
package
,可以保留扩展路径,并赋予
package
sudo权限(一石两鸽)。因此,响应实际上取决于您启动的命令sudo的路径解析是另一个问题-如果有人在搜索该问题时找到此帖子,我建议查看
$ ./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.