我需要从非 BASH 脚本(即 PHP 脚本)执行许多管道 shell 命令,如下所示:
command1 | command2 | command3
因此,如果command1
失败并返回非零退出代码,则其他每个命令也会失败。到目前为止,我想到的是:
set -o pipefail && command1 | command2 | command3
但即使它可以从终端正常运行,但如果从脚本执行,它会产生以下结果:
sh: 1: 设置:非法选项 -o pipefail
答案1
从 Bash 命令行,你需要调用子 shell 以避免pipefail
随后被设置:
$ (set -o pipefail && command1 | command2 | command3)
这会将该选项的效果限制pipefail
在由括号创建的子 shell 内(...)
。
一个真实的例子:
$ (set -o pipefail && false | true) && echo pipefail inactive || echo pipefail active
pipefail active
如果你使用带有选项的显式 shell 调用,则-c
不需要子 shell,无论是带有bash
还是带有sh
别名bash
:
$ bash -c "set -o pipefail && false | true" && echo pipefail inactive || echo pipefail active
pipefail active
$ sh -c "set -o pipefail && false | true" && echo pipefail inactive || echo pipefail active
pipefail active
由于您sh
不接受该pipefail
选项,我不得不假设它要么是某个旧版本或修改版本bash
- 或者它实际上完全是其他 shell。
答案2
不确定为什么上面没有提到,但可以pipefail
使用明确取消设置set +o pipefail
。
set -o pipefail
command1 | command2 | command3
set +o pipefail
如果你正在执行一个片段,并且不确定是否pipefail
已经设置,你可以按照前面的建议将它与子 shell 一起使用:
# explicitly execute with pipefail set
(set -o pipefail ; command1 | command2 | command3 )
# explicitly execute with pipefail unset
(set +o pipefail ; command1 | command2 | command3 )
答案3
您可以将 $(command1) 与 $? 结合使用:
a=$(echo "a")
[ $? -eq 0 ] && b=$(echo $a"b")
[ $? -eq 0 ] && c=$(echo $b"c")
echo $c
打印“abc”
a=$(ls unexitingDir)
[ $? -eq 0 ] && b=$(echo $a"b")
[ $? -eq 0 ] && c=$(echo $b"c")
echo $c
印刷 ””。
“[ $? -eq 0 ] &&” 表示只有前一个命令成功执行,才会执行后面的命令。
这虽然没有回答您的问题,但却可以解决您的问题。