sudo 命令环境变量问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sudo 命令环境变量问题相关的知识,希望对你有一定的参考价值。

参考技术A 问: 普通用户自己添加了 LD_LIBRARY_PATH 环境变量来链接自己所需的库,但当
用sudo 命令运行程序是 LD_LIBRARY_PATH 环境变量变成空了。

答: 当普通用户执行sudo 时 ,系统为了安全会重置环境变量。可用 sudo -l 查看。

问: 按照网上做法,sudoedit /etc/sudoers
将 Defaults env_reset 改为 Defaults !env_reset 为何 sudo 该变量还是为空呢?

答: 原因未知,可能系统环境变量无法重置,sudo 执行命令时会 加载 /etc/environment 中的环境变量,LD_LIBRARY_PATH 在 /etc/environment 未配置。所以导致为空。

解决方法:
vim ~/.bashrc 或者 vim ~/.bash_profile 等 添加如下

测试脚本如下

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

【中文标题】使用sudo时如何保留环境变量【英文标题】:How to keep environment variables when using sudo 【发布时间】:2012-01-27 20:10:59 【问题描述】:

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

【问题讨论】:

superuser.com/questions/232231/… 相关:Why are PATH variables different when running via sudo and su? Unix SE 【参考方案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 产生一个带引号的字符串。与 the parameter expansion in bash 4.4 不同,这适用于 bash 版本

【讨论】:

你就是男人,@Bruno,你就是男人。谢谢【参考方案2】:

如果您需要将环境变量保存在脚本中,您可以将命令放在这样的文档中。尤其是如果你有很多变量来设置这样的东西看起来很整洁。

# 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

【讨论】:

【参考方案3】:

首先你需要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.

【讨论】:

唯一的问题是修改一些配置文件,例如 pacman for arch 以使 -E 通过 要允许 wget 使用 -E(保留环境),您需要在允许运行 wget 的 sudo 规则上指定 SETENV 标记 -- 示例: ALL=(root) NOPASSWD: SETENV: 如果变量是 PATH 或 PYTHONPATH,则此“-E”不起作用。 也不适用于任何LC_* 变量。所以只需使用export LOL_FOO=$LC_FOO 并改用LOL_FOO 这不适用于在.bashrc 文件中向PATH 添加一个元素的更简单的情况——比如export PATH=myPath:$PATH。如果我输入sudo -E bash -c 'echo $PATH',那么PATH 不包含myPath 可能是因为sudo 在调用bash 之前已经禁用了PATH 的本地值。相反,我发现***.com/a/33183620/5459638下面的答案有效,即sudo PATH=$PATH command【参考方案4】:

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

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"

【讨论】:

这可以说是避免信息泄露和安全漏洞的最佳选择。 sudo -E 是确保一次性获得相同效果的可靠方法 我遇到了一个进程调用 sudo (jhbuild) 的问题,我不能告诉它将 -E 标志传递给 sudo,所以这是我的解决方案。 请注意,您应该永远直接编辑etc/sudoers。相反,请使用visudo 命令,该命令会在覆盖sudoers 文件之前对您的编辑进行语法检查。这样,如果您在编辑时犯了错误,就不会把自己锁在外面。 考虑使用大写的环境变量。在我的情况下,使用 HTTP_PROXY 和 HTTPS_PROXY 就可以了。 根据我的经验,小写变体更好,因为它适用于 wget 和 curl。【参考方案5】:

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

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

【讨论】:

我已经在.bashrc 文件中添加到PATH 的某些myPath 下测试了package 的这个答案(带有export 子句)。然后sudo PATH=$PATH which package 找到正确答案,这与sudo which package 不同。但是,sudo PATH=$PATH package 不会比sudo package 更进一步(找不到文件)。另一方面,从用sudo bash 调用的shell 启动一个普通的package 会保留扩展路径并赋予package sudo 权限(两只鸽子和一块石头)。所以响应真的取决于你正在启动哪些命令 sudo 的路径解析是另一回事 - 如果有人找到这篇文章来搜索这件事,我建议查看 unix.stackexchange.com/questions/83191/…【参考方案6】:

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

Defaults env_keep += "http_proxy https_proxy"

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

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

【讨论】:

以上是关于sudo 命令环境变量问题的主要内容,如果未能解决你的问题,请参考以下文章

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

SUDO的环境变量为何不同?

解决sudo用户找不到环境变量的问题

sudo保持环境变量

linux命令su,sudo 使用和区别

sudo如何保持当前用户的环境变量?