Linux 使用命令或 bash 脚本清理环境?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9671027/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 05:07:55  来源:igfitidea点击:

Sanitize environment with command or bash script?

linuxbash

提问by Otto Ulec

In Bash shell, I want to sanitize the environment as the first thing when running with a command.

在 Bash shell 中,我想在使用命令运行时首先清理环境。

I want to unset all the environment variables and only set the ones that are critical for the shell to function, plus the ones the ones needed by my script to complete it's task.

我想取消设置所有环境变量,只设置对 shell 运行至关重要的环境变量,以及脚本完成任务所需的环境变量。

Is there a way to do this in a simple and clean way?

有没有办法以简单而干净的方式做到这一点?

回答by chrisaycock

This worked when I tried it:

当我尝试时,这有效:

for c in $(set | cut -d '=' -f 1); do unset $c; done

It spewed errors on the const variables, but I was able to ignore them.

它在 const 变量上产生错误,但我能够忽略它们。

回答by Eduardo Ivanec

You can use envand a wrapper script:

您可以使用env和包装脚本:

#!/bin/bash
env -i /path/to/main_script.sh

From man env:

来自man env

   -i, --ignore-environment
          start with an empty environment
   -i, --ignore-environment
          start with an empty environment

You can also, of course, just run the script as env -i script.shif you are running it by hand. Unfortunately as far as I can tell one can't use the script shebang to run bashthrough envlike this; the shebang can only accept two parameters by definition as parsed by the kernel.

当然,您也可以像env -i script.sh手动运行脚本一样运行脚本。不幸的是,据我可以告诉一个不能使用脚本家当运行bash通过env这样的; 根据内核解析的定义,shebang 只能接受两个参数。

The other semi-reliable solution using envor exec -c(which does pretty much the same) that I can think of would be to use exec -c $0to re-run the script with a clean environment if you detect it's not clean. Assuming $HOMEis set in an unclean environment and is not set in a clean one (that's true in my install):

我能想到的另一个使用envor exec -c(其作用几乎相同)的半可靠解决方案是,exec -c $0如果您检测到它不干净,则使用干净的环境重新运行脚本。假设$HOME设置在不干净的环境中并且没有设置在干净的环境中(在我的安装中是这样):

#!/bin/bash
[ "$HOME" != "" ] && exec -c 
$ env -i bash -c 'printf "%s\n" "${?+?=$?}" "${#+#=$#}" "${*+*=$*}" "${@+@=$@}" "${-+-=$-}" "${!+!=$!}" "${_+_=$_}" "${$+$=$$}"; env'
?=0
#=0

-=hB

_=bash
$=26927
PWD=/home/username/INVENTORY
SHLVL=1
_=/usr/bin/env
# rest of the script here

回答by l0b0

Expanding on Eduardo's answer:

扩展爱德华多的回答

el@defiant ~$ LOCAL_DOGE="such variable"
el@defiant ~$ ENVIRONMENT_DOGE="much code"
el@defiant ~$ export ENVIRONMENT_DOGE
el@defiant ~$ set | grep DOGE
ENVIRONMENT_DOGE='much code'
LOCAL_DOGE='such variable'
el@defiant ~$ env | grep DOGE
ENVIRONMENT_DOGE=much code
el@defiant ~$ env -i bash
el@defiant ~$ set | grep DOGE
el@defiant ~$ env | grep DOGE
el@defiant ~$

In other words, the following variables are defined in a script run with env -iandshown by env:

换句话说,下面的变量是在与脚本运行定义env -i所示env

  • $PWD(working directory)
  • $SHLVL(number of shells within shells)
  • $_(final argument of previous command)
  • $PWD(工作目录)
  • $SHLVL(壳内壳数)
  • $_(上一个命令的最后一个参数)

The following variables are alsodefined, but notshown by env:

以下变量也是定义,但没有被显示env

  • $?(result of last command)
  • $#(number of arguments)
  • $-(flags passed to the script)
  • $$(PID of the script)
  • $?(最后一个命令的结果)
  • $#(参数数量)
  • $-(传递给脚本的标志)
  • $$(脚本的PID)

回答by Eric Leschinski

Unset all environment variables bash linux

取消设置所有环境变量 bash linux

Command: env -i bash

命令: env -i bash

Example, create local and environment variables, then reset to defaults:

例如,创建本地和环境变量,然后重置为默认值:

env - /bin/bash

So wow, LOCAL_DOGEand ENVIRONMENT_DOGEare gone with one command.

所以,哇,LOCAL_DOGE并且ENVIRONMENT_DOGE都走了一个命令。

Unset all environment variables bash linux, alternate way.

取消设置所有环境变量 bash linux,替代方法。

el@defiant ~$ DOGE1="one"
el@defiant ~$ export DOGE2="two"
el@defiant ~$ set | grep DOGE
DOGE1=one
DOGE2=two
el@defiant ~$ env | grep DOGE
DOGE2=two
el@defiant ~$ env - /bin/bash
el@defiant ~$ set | grep DOGE
el@defiant ~$ env | grep DOGE

Example:

例子:

proxyless () {
  cmd=(unset http_proxy https_proxy \; ${@})
  bash -c "${cmd[*]}"
}

回答by PEdroArthur

I came across this problem while trying to make a helper function to avoid the proxy. I came to call it proxyless. Its code follows:

我在尝试创建辅助函数以避免代理时遇到了这个问题。我是来叫它的proxyless。其代码如下:

$ proxyless curl google.com

What I am doing effectively is building a command array to pass to bash. So, I use unsetto do the obvious, and I put all the command arguments to the end of the array. So, for example,

我正在有效地做的是构建一个命令数组以传递给 bash。所以,我习惯于unset做显而易见的事情,并将所有命令参数放在数组的末尾。所以,例如,

$ bash -c 'unset http_proxy https_proxy; curl google.com'

will become (according to bash -x)

将成为(根据bash -x

while IFS='=' read -rd '' name value ; do unset "$name" ; done < /proc/self/environ

回答by Vladimir Panteleev

Here is a way to do this without starting a new shell, and that will work even with weird variable names (containing whitespace/newlines):

这是一种无需启动新外壳即可执行此操作的方法,即使使用奇怪的变量名称(包含空格/换行符)也可以使用:

##代码##

The disadvantage is that it is Linux-specific, and relies on procfs being mounted.

缺点是它是 Linux 特定的,并且依赖于安装的 procfs。

This will unset allenvironment variables, even HOMEand PATH. This may or may not be what you want.

这将取消设置所有环境变量,甚至HOMEPATH. 这可能是也可能不是您想要的。

Explanation: /proc/PID/environcontains the process's environment block, as a series of zero-delimited NAME=VALUEstrings. We use a readloop, setting the field separator IFSto =so that we can split the name and value from each string. By setting the line delimiter (-d) to an empty string, we cause readto use the null character (the "first" character of a null-terminated string) to split lines. Then, just unset each name in turn (taking care to quote it).

说明:/proc/PID/environ包含进程的环境块,作为一系列以零分隔的NAME=VALUE字符串。我们使用一个read循环,将字段分隔符设置为IFS=以便我们可以从每个字符串中拆分名称和值。通过将行分隔符 ( -d) 设置为空字符串,我们read可以使用空字符(以空字符结尾的字符串的“第一个”字符)来分割行。然后,依次取消设置每个名称(注意引用它)。