考虑以下:
command1 | command2 | command3
据我了解,流水线会运行每个命令,而不管可能发生的任何错误。当命令返回stderr时,它不会通过管道传递到下一个命令,但是下一个命令仍将运行(除非使用|&
)。我想要终止其余管道可能发生的任何错误。我以为set -o pipefail
可以做到这一点,但是如果管道中的任何内容失败,它只会终止管道之后可能发生的任何事情,即:
(set -o pipefail; cmd1 | cmd2 && echo "I won't run if any of the previous commands fail")
那么,如果任何一条命令失败,最简洁的方法是终止管道的其余部分?我还需要它以失败的命令的正确stderr退出。我是从命令行上下文而不是Shell脚本执行此操作的,因此,我为什么要简短一些。有什么想法吗?
我相信,由于管道的执行方式,您所要求的是不可能直接实现的。当外壳程序在管道中执行“稍后”命令时,外壳程序不知道命令的成功或失败(返回值)。它实际上同时运行所有它们,然后收集结果。
有一些变通办法可能会有所帮助。
一次执行一个命令并缓存结果。这样做会更好,因为如果先前的命令失败,则以后的命令绝对不会运行。
一个非常简短的脚本示例:
cache_file=`tempfile`
if command1 > $cache_file ; then
command2 < $cache_file
fi
rm $cache_file
执行所有操作,但检查返回结果无论如何,此命令仍将运行所有命令,但确实可以让您返回原因。
在此,每个命令的STDERR使用重定向到一个不同的文件2>
。然后PIPESTATUS
检查以找到每个命令的返回码。
command1 2> command1_err.log | command2 2> command2_err.log
for result in ${PIPESTATUS[@]} ; do
if [ $result -ne 0 ] ; then
echo command failed
fi
done
要创建管道,shell遵循与这些步骤相似的步骤:
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句