Linux 使用命令或bash脚本清理环境?
在bashshell中,我希望在使用命令运行时首先清理环境 我想取消设置所有环境变量,只设置那些对shell运行至关重要的变量,以及脚本完成任务所需的变量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 从
有没有一种简单而干净的方法可以做到这一点?当我尝试时,这种方法奏效了:
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)$$
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