【问题标题】:Why does redirect with &> change the exit code in zsh?为什么用 &> 重定向会改变 zsh 中的退出代码?
【发布时间】:2024-04-16 05:15:01
【问题描述】:

我在调试一个shell脚本,问题是下面的代码

if curl doesntexist -i &> /dev/null;
then
        echo True 
else
        echo False
fi 

如果运行 zsh,则不等于:

if curl 6 -i 1> /dev/null 2> /dev/null;
then
        echo True 
else
        echo False
fi 

后面的回显如预期的那样为真,但如果我用 &> 重定向,则输出为假。 我不明白这种行为,例如here 它说

&>name is like 1>name 2>name

谁能解释一下为什么两个 sn-ps 在 zsh 中运行时的行为不一样?从 zsh docu 它说它还应该重定向 stdout 和 stderr,听起来它应该和 bash 中的一样:

&> 以'> word'的方式重定向标准输出和标准错误(文件描述符2)

【问题讨论】:

  • 无法重现,按预期工作 - 两者都给出 False
  • 你确定你在bash运行吗? &> 在其他 shell 中不能以同样的方式工作。
  • 是的,刚刚注意到。这是因为我在运行 zsh
  • test.sh 是否有 shebang(#!/bin/zsh 或类似名称)?如果没有,./test.sh 在从 bash 运行时将使用 bash 执行,但从 zsh 运行时使用 /bin/sh
  • &> 不是/bin/sh 中公认的重定向运算符;它可能被解析为两个单独的命令:curl 在后台运行,&(其退出状态始终为 0;curl 本身的退出状态不相关)和一个空命令 @987654339 @ 也始终具有退出状态 0:因此采用 True 路径。

标签: bash zsh


【解决方案1】:

我怀疑你的脚本没有一个 shebang 来指示应该使用哪个 shell 来执行它,你已经让它可执行,并且正在使用类似 ./test.sh 的东西来执行它。如果是这种情况,添加 #!/bin/bash#!/bin/zsh 之类的内容即可解决问题。


如果没有 shebang,实际执行脚本的内容取决于您从哪个 shell 执行它。 bash 将使用bash 执行脚本。但是,zsh 将使用 /bin/sh 执行脚本。

bash 中,&> 是一个重定向运算符,将标准错误和标准输入重定向到同一个文件。

不过,在/bin/sh 中,它不是重定向运算符。命令curl doesntexist -i &> /dev/null 被解析为两个单独的命令:

curl doesntexist -i &
> /dev/null

第一个在后台运行curl,并立即以 0 退出状态返回。 (从不考虑curl 本身的退出状态。)第二个命令是一个有效的空命令,它只是打开> /dev/null 进行写入,然后以0 退出状态退出。

因此,无论curl 可能做什么,if 关心的退出状态只是列表中的最后一个,即> /dev/null 的退出状态。因为它是 0,所以你会得到 True 路径。

bash 中,&> 是有效的重定向运算符,if 按预期查看curl 的退出状态。

【讨论】:

    最近更新 更多