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

Linux 使用命令或bash脚本清理环境?,linux,bash,Linux,Bash,在bashshell中,我希望在使用命令运行时首先清理环境 我想取消设置所有环境变量,只设置那些对shell运行至关重要的变量,以及脚本完成任务所需的变量 有没有一种简单而干净的方法可以做到这一点?当我尝试时,这种方法奏效了: for c in $(set | cut -d '=' -f 1); do unset $c; done 它在常量变量上抛出错误,但我能够忽略它们。您可以使用env和包装器脚本: #!/bin/bash env -i /path/to/main_script.sh 从

在bashshell中,我希望在使用命令运行时首先清理环境

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


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

当我尝试时,这种方法奏效了:

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

它在常量变量上抛出错误,但我能够忽略它们。

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

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

当然,如果手动运行脚本,也可以将其作为
env-iscript.sh
运行。不幸的是,据我所知,不能使用脚本shebang通过
env
这样运行
bash
;shebang只能根据内核解析的定义接受两个参数

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

扩展到:

换句话说,以下变量在使用
env-i
运行的脚本中定义,并由
env
显示:

  • $PWD
    (工作目录)
  • $SHLVL
    (壳中的壳数)
  • (上一个命令的最终参数)
以下变量也已定义,但未在
env
中显示:

  • $?
    (最后一个命令的结果)
  • $#
    (参数数量)
  • $-
    (传递到脚本的标志)
  • $$
    (脚本的PID)
取消设置bash linux的所有环境变量 命令:
env-ibash

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

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 ~$
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
哇,
LOCAL\u-DOGE
ENVIRONMENT\u-DOGE
只需一个命令就消失了

以另一种方式取消设置bash linux中的所有环境变量。 示例:

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

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

proxyless () {
  cmd=(unset http_proxy https_proxy \; ${@})
  bash -c "${cmd[*]}"
}
我正在有效地构建一个命令数组以传递给bash。因此,我使用
unset
来执行显而易见的操作,并将所有命令参数放在数组的末尾。那么比如说,

$ proxyless curl google.com
将成为(根据
bash-x


下面是一种不启动新shell的方法,即使使用奇怪的变量名(包含空格/换行符),也可以这样做:

而IFS='='read-rd''名称值;不取消设置“$name”;完成
缺点是它是特定于Linux的,并且依赖于安装的procfs

这将取消设置所有环境变量,即使是
HOME
PATH
。这可能不是你想要的


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

我喜欢
exec-c
。以一些脆性为代价,您可以将其增强为:
[“$(env |/bin/sed-r-e'/^(PWD | SHLVL | | | u)=/d')”]&&exec-c$0
。也就是说,它坚持清除所有内容,但bash似乎自动设置的一些内容除外。请注意,通过使用
env-i
exec
,您也将丢失非环境(即非导出)shell变量。至于shebang问题:coreutils'
env
获得了一个选项
-S
,该选项解决了此问题:此选项需要一个在空白处拆分的字符串来形成要调用的命令。因此,我们的shebang可以写成
#/bin/env-iS/bin/bash
。此选项甚至支持设置变量,以便我们可以保留一些变量,例如路径和术语:
#/bin/env-iS PATH=${PATH}TERM=${TERM}/bin/bash
。请参阅。
env-ibash-c
非常完美!我得到我的默认环境,同时清除所有其他东西,谢谢!您不需要保存/还原
$?
$#
等。这些实际上不是环境的一部分-它们是内部shell变量。在Bash中,
env
命令有一个标记
-i
,它将清除所有环境变量,使其成为登录默认值。所以运行以下命令:
env-ibash
这并不是真正的“在bash中”-
env
是一个标准的UNIX命令,而不是bash内置命令。您可以在没有shell的情况下(从C、从Python等)调用它。我会使用
env
而不是
set
,因为后者也会打印bash中的函数;或者至少不是一个正确的答案。您在这里所做的只是一个新的子shell,没有继承旧环境。如果你这样做几次,你就会耗尽内存:p。同意卡洛的观点,这绝对不是一个解决方案。。。它不会取消设置变量,它会启动一个新会话。不会正确处理空白。请尝试:
proxyless printf'%q\n'a b'c d'$'e\nf'
并比较没有
proxyless
的输出。此外,问题是如何删除所有环境变量。@CharlesDuffy您的陈述很容易被
env$'a\nb=c\nd'bash-c env
(bash 4.4.23(1)-发行版)推翻。或者你是说别的什么?。。。
proxyless () {
  cmd=(unset http_proxy https_proxy \; ${@})
  bash -c "${cmd[*]}"
}
$ proxyless curl google.com
$ bash -c 'unset http_proxy https_proxy; curl google.com'
while IFS='=' read -rd '' name value ; do unset "$name" ; done < /proc/self/environ