我尝试了以下方法,但似乎不起作用:
$ 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”,则将脚本替换为exec
using-a
使ARGV[0]
(因此$_
)只是“bash”,并使用 using-c
清除环境。
或者,如果可以在脚本开始时清理环境(仅限 bash):
#!/bin/sh
unset $(compgen -e)
# your script here
它使用compgen
(completion helper) 列出所有导出的环境变量的名称,并unset
一次性保存它们。
也可以看看shebang 中的多个参数有关 Shebang 行为一般问题的更多详细信息。