如何在干净的环境中启动脚本?

如何在干净的环境中启动脚本?

我尝试了以下方法,但似乎不起作用:

$ cat script.sh
#!/bin/env -i /bin/sh

/bin/env
$ script.sh
/bin/env: invalid option -- ' '
Try `/bin/env --help' for more information.

答案1

这不起作用的原因是因为它将视为-i /bin/sh的单个参数env。通常这将是 2 个参数,-i并且/bin/sh.这只是 shebang 的一个限制。没有办法解决它。


不过,您仍然可以执行此任务,只是采用不同的方式。

如果您希望此任务由脚本本身执行,而不必执行类似的操作env -i script.sh,则可以让脚本自行重新执行。

#!/bin/sh
[ -z "$CLEANED" ] && exec /bin/env -i CLEANED=1 /bin/sh "$0" "$@"

CLEANED如果未设置环境变量,这将导致脚本重新执行自身。然后在重新执行时,它设置变量以确保它不会进入循环。

答案2

使用以下命令运行您的脚本env -i

env -i script.sh

和往常一样的脚本:

#!/bin/sh
# ... your code here

如果您打算在干净的环境中运行而无需在运行时明确说明。 Eduardo Ivanec 给出了一些想法这个答案exec,当环境不干净时(例如定义了 $HOME ),您可以递归调用脚本:

[ "$HOME" != "" ] && exec -c $0

答案3

使用 bash,你可以这样做:

#!/usr/bin/bash

set -e
set -u

[ -v HOME ] && exec -c "$0" "$@"

# continue with the rest of the script
# e.g. print the cleaned environment:
export

set -e和命令set -u 并不是绝对必要的,但我包含它们是为了证明这种方法不依赖于访问未设置的变量(例如[ "$HOME" != "" ])并且与设置兼容set -e

测试HOME变量应该是安全的,因为 bash 以非交互模式执行脚本,即~/.bashrc在启动期间不会获取诸如(可以设置环境变量的位置)之类的配置文件。

输出示例:

declare -x OLDPWD
declare -x PWD="/home/juser"
declare -x SHLVL="1"

答案4

大多数答案都指出了 Linux 2 参数 shebang 限制(解释器 + 单参数),但说不能这样做是不正确的 - 您只需要更改为可以使用单个参数执行有用操作的解释器:

#!/usr/bin/perl -we%ENV=();exec "/bin/sh " . join " ", map "'$_'", @ARGV;
# your sh script here

其作用是perl使用单行脚本 ( -e) 进行调用,该脚本会清除%ENV(比 便宜env -i)并调用exec /bin/sh,并正确引用参数。如果需要,可以添加更多perl逻辑(尽管在 Linux 上不会太多,因为字符数有限BINPRM_BUF_SIZE,可能是 128 个)。有一个变化,使用awk 在这个答案中对这个问题shebang 中的多个参数

遗憾的是,这是 Linux 特有的,它不适用于允许多个 shebang 参数的系统:-/

perl将此字符串作为单个参数处理,所以它是未引用上面就像您通常perl -e ...从命令行执行的操作一样(如果您要添加引号,这些引号会被保留,perl 只会看到一个文字字符串,上面有警告会抱怨一个无用的常量)。

另请注意,以这种方式使用时,行为会略有变化,@ARGV通常仅包含参数,并$0包含脚本名称,但使用此 shebang$ARGV[0]是脚本的名称,这使得创建exec()参数更容易(并且$0包含-e)。

您还可以使用解释器来解决此问题,该解释器“重新处理”其命令行(无需额外-c参数),就像古老的 AT&Tksh93所做的那样:

#!/bin/ksh /usr/bin/env -i /bin/sh

虽然现在可能ksh不那么常见了;-)

bash与 具有类似的功能--wordexp它在它工作的版本中是“未记录的”,并且在其记录的版本中在编译时未启用:-/它也不能用于此目的,因为它需要两个参数...)

另外,实际上是@Patrick 和@maxschlepzig 答案的变体:

#!/bin/bash
[ "$_" != bash ] && exec -c -a "bash" /bin/bash "$0" "$@"
# your script here

它不使用新变量,而是使用特殊的“ _”变量,如果它没有设置为完全“bash”,则将脚本替换为execusing-a使ARGV[0](因此$_)只是“bash”,并使用 using-c清除环境。

或者,如果可以在脚本开始时清理环境(仅限 bash):

#!/bin/sh
unset $(compgen -e)
# your script here

它使用compgen(completion helper) 列出所有导出的环境变量的名称,并unset一次性保存它们。

也可以看看shebang 中的多个参数有关 Shebang 行为一般问题的更多详细信息。

相关内容