在Bash shell中,我想在使用命令运行时首先清理环境。
我想取消设置所有的环境variables,只设置那些对shell运行至关重要的环境variables,加上脚本所需的那些variables来完成它的任务。
有没有办法以一种简单而干净的方式做到这一点?
你可以使用env
和一个包装脚本:
#!/bin/bash env -i /path/to/main_script.sh
从man env
:
-i, --ignore-environment start with an empty environment
当然,如果你正在手动运行脚本,也可以像脚本一样运行脚本。 不幸的是,据我所知,不能使用脚本shebang像这样通过env
运行bash
; shebang只能接受由内核解析的两个参数。
另一个使用env
或exec -c
半可靠解决方案(几乎相同)我可以想到的是,如果检测到不干净,则使用exec -c $0
重新运行脚本,并使用干净的环境。 假设$HOME
被设置在一个不干净的环境中,并且没有设置成干净的(在我的安装中是这样的):
#!/bin/bash [ "$HOME" != "" ] && exec -c $0 # rest of the script here
命令: 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
这工作时,我试了一下:
for c in $(set | cut -d '=' -f 1); do unset $c; done
它在const变量上喷出错误,但是我可以忽略它们。
扩展Eduardo的答案 :
$ 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 -i
显示:
$PWD
(工作目录) $SHLVL
(壳内的壳数) $_
(前一个命令的最后一个参数) 以下变量也被定义,但不能被env
:
$?
(最后一个命令的结果) $#
(参数个数) $-
(传递给脚本的标志) $$
(脚本的PID) 我试图做一个帮手函数,以避免代理遇到这个问题。 我来叫它无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'