管道中捕获错误代码

管道中捕获错误代码

本文介绍了在 shell 管道中捕获错误代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前有一个执行类似操作的脚本

I currently have a script that does something like

./a | ./b | ./c

我想修改它,以便如果 a、b 或 c 中的任何一个以错误代码退出,我会打印一条错误消息并停止而不是将错误的输出向前输送.

I want to modify it so that if any of a, b or c exit with an error code I print an error message and stop instead of piping bad output forward.

最简单/最干净的方法是什么?

What would be the simplest/cleanest way to do so?

推荐答案

如果您真的不想在第一个命令成功之前继续执行第二个命令,那么您可能需要使用临时文件.简单的版本是:

If you really don't want the second command to proceed until the first is known to be successful, then you probably need to use temporary files. The simple version of that is:

tmp=${TMPDIR:-/tmp}/mine.$$
if ./a > $tmp.1
then
    if ./b <$tmp.1 >$tmp.2
    then
        if ./c <$tmp.2
        then : OK
        else echo "./c failed" 1>&2
        fi
    else echo "./b failed" 1>&2
    fi
else echo "./a failed" 1>&2
fi
rm -f $tmp.[12]

1>&2"重定向也可以缩写为>&2";然而,旧版本的 MKS shell 在没有前面的1"的情况下错误地处理了错误重定向,所以我多年来一直使用这种明确的可靠性表示法.

The '1>&2' redirection can also be abbreviated '>&2'; however, an old version of the MKS shell mishandled the error redirection without the preceding '1' so I've used that unambiguous notation for reliability for ages.

如果您中断某事,这会泄漏文件.防弹(或多或少)shell 编程使用:

This leaks files if you interrupt something. Bomb-proof (more or less) shell programming uses:

tmp=${TMPDIR:-/tmp}/mine.$$
trap 'rm -f $tmp.[12]; exit 1' 0 1 2 3 13 15
...if statement as before...
rm -f $tmp.[12]
trap 0 1 2 3 13 15

第一行陷阱显示运行命令"rm -f $tmp.[12];exit 1' 当任何信号 1 SIGHUP、2 SIGINT、3 SIGQUIT、13 SIGPIPE 或 15 SIGTERM 出现时,或 0(当 shell 出于任何原因退出时).如果您正在编写 shell 脚本,则最终陷阱只需要删除 0 上的陷阱,即 shell 退出陷阱(您可以保留其他信号,因为进程无论如何都将终止).

The first trap line says 'run the commands 'rm -f $tmp.[12]; exit 1' when any of the signals 1 SIGHUP, 2 SIGINT, 3 SIGQUIT, 13 SIGPIPE, or 15 SIGTERM occur, or 0 (when the shell exits for any reason).If you're writing a shell script, the final trap only needs to remove the trap on 0, which is the shell exit trap (you can leave the other signals in place since the process is about to terminate anyway).

在原始管道中,在 'a' 完成之前,'c' 从 'b' 读取数据是可行的 - 这通常是可取的(例如,它提供了多个内核的工作).如果b"是排序"阶段,那么这将不适用——b"必须先查看所有输入,然后才能生成任何输出.

In the original pipeline, it is feasible for 'c' to be reading data from 'b' before 'a' has finished - this is usually desirable (it gives multiple cores work to do, for example). If 'b' is a 'sort' phase, then this won't apply - 'b' has to see all its input before it can generate any of its output.

如果你想检测哪些命令失败,你可以使用:

If you want to detect which command(s) fail, you can use:

(./a || echo "./a exited with $?" 1>&2) |
(./b || echo "./b exited with $?" 1>&2) |
(./c || echo "./c exited with $?" 1>&2)

这既简单又对称 - 扩展到 4 部分或 N 部分管道是微不足道的.

This is simple and symmetric - it is trivial to extend to a 4-part or N-part pipeline.

使用set -e"的简单实验没有帮助.

Simple experimentation with 'set -e' didn't help.

这篇关于在 shell 管道中捕获错误代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-26 10:58