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

发布于 2024-12-23 00:36:36 字数 1560 浏览 0 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

香草可樂 2024-12-30 00:36:36

首先,您需要导出 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.

First you need to export HTTP_PROXY. Second, you need to read man sudo, and look at the -E flag. This works:

$ 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.
香草可樂 2024-12-30 00:36:36

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

Defaults env_keep += "ftp_proxy http_proxy https_proxy no_proxy"

取自 ArchLinux 维基

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

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

The trick is to add environment variables to sudoers file via sudo visudo command and add these lines:

Defaults env_keep += "ftp_proxy http_proxy https_proxy no_proxy"

taken from ArchLinux wiki.

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

Defaults  env_keep += "http_proxy"
Defaults  env_keep += "https_proxy"
Defaults  env_keep += "HTTP_PROXY"
Defaults  env_keep += "HTTPS_PROXY"
一人独醉 2024-12-30 00:36:36

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

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

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"
挽梦忆笙歌 2024-12-30 00:36:36

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

Defaults env_keep += "http_proxy https_proxy"

您还应该考虑指定 env_keep 仅适用于像这样的单个命令:

Defaults!/bin/[your_command] env_keep += "http_proxy https_代理”

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

Defaults env_keep += "http_proxy https_proxy"

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

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

生生不灭 2024-12-30 00:36:36

一个简单的包装函数(或内联 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 生成一个 shell 带引号的字符串。与 bash 4.4 中的参数扩展不同,这适用于 bash 版本 << 4.0

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

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

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 %q produces a shell quoted string. Unlike the parameter expansion in bash 4.4, this works in bash versions < 4.0

谁的年少不轻狂 2024-12-30 00:36:36

将代码片段添加到 /etc/sudoers.d

不知道这是否在所有发行版中都可用,但在基于 Debian 的发行版中,在 /etc/sudoers 包含文件夹 /etc/sudoers.d 的文件。在此,可以添加修改 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 中的环境配置可以在 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 的后续列表中。

Add code snippets to /etc/sudoers.d

Don't know if this is available in all distros, but in Debian-based distros, there is a line at or near the tail of the /etc/sudoers file that includes the folder /etc/sudoers.d. Herein, one may add code "snippets" that modify sudo's configuration. Specifically, they allow control over all environment variables used in sudo.

As with /etc/sudoers, these "code snippets" should be edited using visudo. You can start by reading the README file, which is also a handy place for keeping any notes you care to make:

$ 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

Read the "Command Environment" section of 'man 5 sudoers'

Perhaps the most informative documentation on environment configuration in sudo is found in the Command environment section of man 5 sudoers. Here, we learn that a sudoers environment variables that are blocked by default may be "whitelisted" using the env_check or env_keep options; e.g.

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

And so, in the OP's case, we may "pass" the sudoer's environment variables as follows:

$ 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!

Get your bearings from '# sudo -V'

The OP presumably discovered the missing environment variable in sudo by trial-and-error. However, it is possible to be proactive: A listing of all environment variables, and their allowed or denied status is available (and unique to each host) from the root prompt as follows:

# sudo -V
...
Environment variables to check for safety: 
...
Environment variables to remove: 
...
Environment variables to preserve:
...

Note that once an environment variable is "whitelisted" as above, it will appear in subsequent listings of sudo -V under the "preserve" listing.

落叶缤纷 2024-12-30 00:36:36

如果您需要将环境变量保留在脚本中,您可以将命令放在此处的文档中,如下所示。特别是如果你有很多变量来让事情看起来很整洁。

# 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

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.

# 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文