如果任何函数并行失败,则停止 bash

Stop bash if any of the functions fail in parallel

我的 BASH 中有 BASH 到 运行 3 个并行函数。

        functionA () {
            ......
            my command || { echo "ERROR!!" >> $LOG_FILE ; exit 1 ;}
        }

        functionB () {
            ......
            my command || { echo "ERROR!!" >> $LOG_FILE ; exit 1 ;}
        }
       
        functionC () {
            ......
            my command || { echo "ERROR!!" >> $LOG_FILE ; exit 1 ;}
        }

functionA &
functionB &
functionC &
wait

我在所有函数中都有一些命令用于错误处理,如下所示:

my command || { echo "ERROR!!" >> $LOG_FILE ; exit 1 ;}

我注意到即使我在所有函数中都有用于错误处理的出口 1,但其他函数仍在继续。如果任何函数失败,如何停止 bash 和 return 退出代码 1?

我是 BASH 的新手,非常感谢您的帮助!

update: 用大量 sub-processes 同时终止测试我的原始代码表明需要某种独占锁定机制;我使用广泛可用的 mktemp -d 和符号链接实现了一个简单的(即原子的)。

#!/bin/bash

lockdir=$(mktemp -d) || exit "$?"

trap 'exit 1' ABRT
trap 'mv "$lockdir" "$lockdir~" && rm -rf "$lockdir~"; kill 0' EXIT

diex() { ln -s _ "$lockdir/.lock" 2> /dev/null && kill -ABRT "$$"; }

{ sleep 1; echo "ERROR!!"; diex; } &
{ sleep 2; echo "HELLO!!"; } &

wait

注:这里我假设"$lockdir~"不存在。如果它对您来说不够好,那么您可以使用 mktemp -d 创建另一个目录,并在删除它之前将其用作 trash-bin。

解释:

想法是让 sub-processes 在失败时用 kill -ABRT "$$" 通知主脚本。
我选择 SIGABRT 信号是因为它适用于中止的目的,但它具有禁用通常在接收 SIGABRT 时自动生成 core-dump 的效果。如果您 运行 正在使用支持 SIGUSR1SIGUSR2 的 OS,那么您可以改用它。

  1. 在脚本的开头,您定义了一些带有 trap 的信号侦听器,并在捕获指定类型的信号时将命令关联为 运行:
  • EXIT 信号的侦听器(例如由主脚本上下文中的 exit 命令触发)将终止脚本及其所有 sub-processes kill 0.

  • SIGABRT的侦听器(由sub-processes发送)不仅会生成EXIT信号,还会将退出状态设置为1.

  1. 锁定机制是为了防止发送一个以上的SIGABRT信号。