Linux 上的 ZSH 无法识别 shell 脚本中的有效选项

ZSH on Linux doesn't recognize valid options in a shell script

zsh 不识别使用 -o 设置的选项,但 仅当 在 shebang 和 Linux 上时。

以下脚本在 zsh 5.0.2zsh 5.6 和最新的 git 上失败:

#!/bin/zsh -o pipefail
thiswillfail | echo 'hello, world'
echo $?
exit

预期输出

hello, world
/home/prajjwal/script:2: command not found: thiswillfail
127

实际输出

/bin/zsh: no such option:  pipefail

有效方法

我试过的

  • 正在清空我的 .zshrc 以确保我的设置不会导致此问题。

一边

虽然我只是想让 pipefail 工作,但它拒绝与我尝试设置的任何其他选项一起工作,即使 zshoptions 中提到了所有这些选项。

这是试图在 #! 行上设置选项的一个陷阱。内核仅在第一个 space.

处拆分 shebang 行

当你说

#!/bin/zsh -o pipefail

最终执行的指令是"/bin/zsh" "-o pipefail" "/home/prajjwal/script".

错误消息说 " pipefail"(注意前导 space)不是有效选项,这是正确的:只有 "pipefail" 有效。

在这种情况下,一个可能的解决方法是将所有内容都塞进一个命令行参数中:

#!/bin/zsh -opipefail

但通常这是不可能的,并且 #! 接口不允许您传递超过一个额外的参数,因此您的选择是找到其他解决方法(例如手动使用 set)或编写包装器脚本:

#!/bin/zsh
exec /bin/zsh -o pipefail /path/to/the/real/script

在某些系统上还有另一种选择:env -S。此选项未由 POSIX 指定,并且并非在所有系统上都可用。它适用于 systems using the GNU tools (including all standard Linux distributions) and FreeBSD, but not OpenBSD or NetBSD。我找不到有关 MacOS 的任何信息。

(注意:GNU env 还支持 --split-string 作为替代(长)选项名称,但 FreeBSD env 不支持。)

用法:

#!/usr/bin/env -S /bin/zsh -o pipefail

这会用一个长参数 ('-S /bin/zsh -o pipefail') 调用 env。标准选项处理将其视为 -S 选项后跟参数 (' /bin/zsh -o pipefail').

在这样一个简单的例子中,env -S 拆分 spaces/tabs 上的参数并将结果列表视为它首先是原始命令行的一部分:

env -S ' /bin/zsh -o pipefail'
# works the same as:
env /bin/zsh -o pipefail

在不太简单的情况下,您必须引用一些字符(env -S 对待 spaces、"'\$ 特别是,等等)。特别是,它 not 像 shell 引用一样工作。有关详细信息,请参阅上面链接的手册页。