zsh
无法识别 -o
设置的选项,但仅当它在 shebang 中时,并且在 Linux
上.
以下脚本在 zsh 5.0.2
上失败, zsh 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
什么有效
zsh 5.3
上的脚本上MacOS Mojave
。这似乎在每个Linux
上都失败了不过,到目前为止我已经尝试过的版本。- 手动调用
/bin/zsh -o pipefail
在终端上 - 使用
set -o pipefail
设置选项在脚本中的 shebang 之后。
我尝试过的
- 清空我的
.zshrc
确保我的设置之一不会导致此问题。
旁白
虽然我只是想得到 pipefail
要工作,这拒绝与我尝试设置的任何其他选项一起使用,即使 zshoptions
中提到了所有这些选项。 .
最佳答案
这是尝试在 #!
行上设置选项的陷阱。内核仅在第一个空格处分割 shebang 行。
当你说
#!/bin/zsh -o pipefail
最终执行的命令是“/bin/zsh”“-o pipelinefail”“/home/prajjwal/script”
。
错误消息表明“pipefail”
(注意前导空格)不是有效选项,这是正确的:只有“pipefail”
有效。
在这种情况下,一个可能的解决方法是将所有内容都塞进一个命令行参数中:
#!/bin/zsh -opipefail
但一般来说这是不可能的,并且 #!
接口(interface)不允许您传递多个额外参数,因此您的选择是寻找其他解决方法(例如使用 set
code> 手动)或编写包装脚本:
#!/bin/zsh
exec /bin/zsh -o pipefail /path/to/the/real/script
在某些系统上,还可以使用另一种替代方法:env -S
。该选项不是由 POSIX 指定的,并且并非在所有系统上都可用。它适用于 systems using the GNU tools (包括所有标准 Linux 发行版)和 FreeBSD ,但不是OpenBSD或NetBSD 。我找不到任何有关 MacOS 的信息。
(注意:GNU env 还支持 --split-string
作为替代(长)选项名称,但 FreeBSD env 不支持。)
用法:
#!/usr/bin/env -S /bin/zsh -o pipefail
这会使用单个长参数调用env
('-S/bin/zsh -o pipelinefail'
)。标准选项处理将其视为 -S
选项后跟一个参数 ('/bin/zsh -o pipelinefail'
)。
在这样的简单情况下,env -S
将参数拆分为空格/制表符,并将结果列表视为最初是原始命令行的一部分:
env -S ' /bin/zsh -o pipefail'
# works the same as:
env /bin/zsh -o pipefail
在不太简单的情况下,您必须引用一些字符(env -S
处理空格、"
、'
、\
、$
特别是等等)。特别是,它不像像 shell 引用那样工作。有关详细信息,请参阅上面链接的手册页。
关于linux - Linux 上的 ZSH 无法识别 shell 脚本中的有效选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53582831/