在Bash shell中,我想在使用命令运行时首先清理环境。
我想取消设置所有环境变量,只设置对shell起作用的关键变量,以及我的脚本完成任务所需的那些变量。
有没有办法以简单干净的方式做到这一点?
答案 0 :(得分:38)
您可以使用env
和包装脚本:
#!/bin/bash
env -i /path/to/main_script.sh
来自man env
:
-i, --ignore-environment start with an empty environment
当然,如果您手动运行脚本,也可以将脚本作为env -i script.sh
运行。不幸的是,据我所知,不能使用脚本shebang来运行bash
到env
这样;根据内核解析,shebang只能接受两个参数。
使用env
或exec -c
(几乎完全相同)的其他半可靠解决方案,我能想到的是使用exec -c $0
重新运行脚本一个干净的环境,如果你发现它不干净。假设$HOME
设置在一个不干净的环境中并且未设置为干净的(在我的安装中是真的):
#!/bin/bash
[ "$HOME" != "" ] && exec -c $0
# rest of the script here
答案 1 :(得分:10)
命令:env -i bash
示例,创建本地和环境变量,然后重置为默认值:
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 ~$
哇,LOCAL_DOGE
和ENVIRONMENT_DOGE
只用了一个命令。
env - /bin/bash
示例:强>
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
答案 2 :(得分:5)
这在我尝试时起作用了:
for c in $(set | cut -d '=' -f 1); do unset $c; done
它在const变量上出现错误,但我能够忽略它们。
答案 3 :(得分:2)
这是一种无需启动新shell即可执行此操作的方法,即使使用奇怪的变量名(包含空格/换行符),该方法也可以使用:
while IFS='=' read -rd '' name value ; do unset "$name" ; done < /proc/self/environ
缺点是它特定于Linux,并且依赖于挂载的procfs。
这将取消设置所有环境变量,甚至HOME
和PATH
。这可能是您想要的,也可能不是。
说明:/proc/PID/environ
包含进程的环境块,为一系列以零分隔的NAME=VALUE
字符串。我们使用read
循环,将字段分隔符IFS
设置为=
,以便我们可以从每个字符串中拆分名称和值。通过将行定界符(-d
)设置为空字符串,我们使read
使用空字符(以空终止的字符串的“第一个”字符)来分割行。然后,只需依次取消设置每个名称(注意将其引用)。
答案 4 :(得分:1)
$ env -i bash -c 'printf "%s\n" "${?+?=$?}" "${#+#=$#}" "${*+*=$*}" "${@+@=$@}" "${-+-=$-}" "${!+!=$!}" "${_+_=$_}" "${$+$=$$}"; env'
?=0
#=0
-=hB
_=bash
$=26927
PWD=/home/username/INVENTORY
SHLVL=1
_=/usr/bin/env
换句话说,以env -i
显示的env
和运行的脚本中定义了以下变量:
$PWD
(工作目录)$SHLVL
(shell中的shell数量)$_
(上一个命令的最后一个参数)以下变量也定义,但env
显示不:
$?
(上一个命令的结果)$#
(参数数量)$-
(传递给脚本的标志)$$
(脚本的PID)答案 5 :(得分:0)
我在尝试创建辅助函数以避免代理时遇到了这个问题。我来称它为proxyless
。其代码如下:
proxyless () {
cmd=(unset http_proxy https_proxy \; ${@})
bash -c "${cmd[*]}"
}
我正在有效地做的是构建一个命令数组以传递给bash。所以,我使用unset
做了显而易见的事情,并将所有命令参数放在数组的末尾。所以,例如,
$ proxyless curl google.com
将成为(根据bash -x
)
$ bash -c 'unset http_proxy https_proxy; curl google.com'