如何在失败后继续级联管道命令

如何在失败后继续级联管道命令

我正在运行命令并使用自己的脚本操作输出,但我不希望主命令在脚本失败时停止。

例如:

a-command | tee logfile.txt | myscript

当我的脚本中途失败时,我查看 logfile.txt,发现它在我的脚本停止工作的地方中断,但我想要的是 a-命令继续运行,而 logfile.txt 具有完整的日志,以便我可以调试我的脚本并修复错误。

修改我的命令以将最后一个管道部分视为可选或在出现错误时被忽略的方法是什么,以便前两个部分(命令和 tee)完成其工作。

[编辑]a-command是一项漫长的任务,我的脚本基本上是在命令运行时操纵输出以更好地报告状态。所以我不想在a-command完成工作后运行我的脚本。

答案1

a-command | tee logfile.txt | { myscript; cat >/dev/null; }

这将首先像往常一样运行您的管道,直到myscript终止(无论出于何种原因)。此时,cat将接管读取操作,tee直到没有更多数据到达为止。读取的数据cat通过管道传输到 来丢弃/dev/null

如果在没有首先结束/失败的情况下a-command完成,将无法读取更多数据并且可能会终止(?)。在终止时,已启动,但由于没有更多数据可供读取,因此它会立即终止并且管道将完成。myscriptmyscriptmyscriptcat


解决 TooTea 的问题评论确保我们仍然获得管道的正确退出状态:

a-command | tee logfile.txt | ( myscript; err=$?; cat >/dev/null; exit "$err" )

答案2

Tee(在 Linux 中)有一个忽略管道故障的选项。

a-command | tee --output-error=warn logfile.txt | myscript

当 myscript 失败或被杀死时,a-命令继续运行并且日志继续增长。

您可以重新运行脚本,并在它捕获日志的最后一个完整块时退出:

myscript < logfile.txt

您可以重新运行脚本,并让它在赶上时等待添加。

tail -999999f < logfile.txt | myscript

一个更复杂的示例,包含在 Bash 脚本中。

logger 代表你的 a 命令。它生成 36 种短字符串排列,每秒一种。所有输出都指向 593580.log。

awk 代表你的“myscript”。它打印输入的子集。

wdog 是我的看门狗实用程序。 -d 5 使其调试其操作。 -t 25 使其在 25 秒后使用 SIGUSR1 使受控制的进程(awk)超时。这只是让我手动运行一个kill来模拟你的脚本失败——我喜欢可重复的测试。

当 awk 消失时,同一复合命令中的 cat 开始读取管道,并将剩余数据复制到重复日志中。因此,您可以针对完整日志或仅针对未处理的数据重新运行脚本,并且可以比较两个日志以准确找到崩溃的位置。

或者,您可以cat >/dev/null只是保持管道处于活动状态,以便记录器继续运行。

两个日志文件副本似乎都是行缓冲的:tail -f 实时显示。

示例脚本:

#! /bin/bash

logger () {

    for Q in {0..1}{A..C}{A..F}; do
        printf '%s\n' "${Q}"
        sleep 1
    done
}
    
AWK='
/C/ { printf ("awk %d %s\n", NR, $0); }
'

    logger | tee 593580.log | 
        { 
            date
            wdog -d 5 -t 25 awk "${AWK}"
            date
            cat > 593580.add 
            date
        }

测试运行:

paul $ ./593580
Thu 18 Jun 15:35:24 BST 2020
wdog       25.000| Thu Jun 18 15:35:49.574 2020
wdog 15:35:24.574| Started awk as 14035
awk 3 0AC
wdog 15:35:29.579| Tick
awk 9 0BC
wdog 15:35:34.583| Tick
awk 13 0CA
awk 14 0CB
awk 15 0CC
wdog 15:35:39.586| Tick
awk 16 0CD
awk 17 0CE
awk 18 0CF
wdog 15:35:44.591| Tick
awk 21 1AC
wdog 15:35:49.579| Tick
wdog 15:35:49.579| Timed out child 14035 with signal 10
wdog 15:35:49.580| Child 14035 terminated with signal 10
Thu 18 Jun 15:35:49 BST 2020
Thu 18 Jun 15:36:00 BST 2020
paul $ 

相关内容