Answers:
之所以不起作用,是因为它被-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
未设置环境变量,这将导致脚本重新执行自身。然后在重新执行时,它会设置变量以确保它不会进入循环。
env
GNU coreutils提供的选项现在可以-S
解决与该问题类似但又不完全相同的问题。例如#!/usr/bin/env -S perl -T
。
#!/usr/bin/env -S -i /bin/sh
。注意可移植性问题。
使用以下命令运行脚本env -i
:
env -i script.sh
和脚本一样:
#!/bin/sh
# ... your code here
如果您要在干净的环境中运行而无需在运行时明确说明。Eduardo Ivanec在此答案中给出了一些想法,您可以exec
在环境不干净时(例如,定义$ HOME)以递归方式调用脚本:
[ "$HOME" != "" ] && exec -c $0
使用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"
在大多数答案中都提到了Linux 2参数的shebang限制(interpeter +单参数),但是不能做到这一点是不正确的-您只需更改为可以对单个参数做一些有用的事情的解释器即可:
#!/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)
可悲的是,这是特定于Linux的,它不能在允许多个shebang参数的系统上运行:-/
perl
将字符串作为一个单独的参数进行处理,因此上面没有像您通常perl -e ...
在命令行中使用的那样对其进行引用(如果要添加引号,则保留这些引号,perl只会看到文字字符串,并带有警告字样会抱怨无用的字符串)不变)。
另请注意,以这种方式使用时,行为上会有细微的变化,@ARGV
通常只包含参数,并$0
包含脚本,但是使用shebang $ARGV[0]
是脚本的名称(和$0
是-e
),这使操作变得容易一些。
您还可以使用解释器解决此问题,该解释器“重新处理”其-c
古老的AT&T的命令行(无需额外的参数)ksh93
:
#!/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
而不是使用一个新变量这里使用了特殊的“ _
”变量,如果没有设置精确“打击”然后替换脚本exec
使用-a
,使ARGV[0]
(因此$_
庆典“并使用)只是” -c
来清除环境。
或者,如果可以在脚本开始时清理环境(仅限bash),则:
#!/bin/sh
unset $(compgen -e)
# your script here
使用compgen
(补全助手)列出所有导出的环境变量的名称,然后unset
一次性完成。
有关shebang行为的一般问题的更多详细信息,另请参见shebang中的Multiple arguments。