Bash 如何使用SIGCHLD处理子级失败时的错误退出代码

Bash 如何使用SIGCHLD处理子级失败时的错误退出代码,bash,sh,Bash,Sh,我有一个shell脚本,它使一堆子进程在后台运行。如果其中任何一个失败,我想用kill--$$终止所有子进程和父进程 我试图在父进程中创建一个更简单的信号处理函数检查\u exit\u code(),看看它是否可以正常工作。每次子进程终止时都会使用trap和SIGCHLD信号调用它 #!/bin/sh set -o monitor function check_exit_code { if [ $1 -eq "0" ] then echo

我有一个shell脚本,它使一堆子进程在后台运行。如果其中任何一个失败,我想用
kill--$$
终止所有子进程和父进程

我试图在父进程中创建一个更简单的信号处理函数
检查\u exit\u code()
,看看它是否可以正常工作。每次子进程终止时都会使用
trap
SIGCHLD
信号调用它

#!/bin/sh
set -o monitor

function check_exit_code {
    if [ $1 -eq "0" ]
    then 
        echo "Success: $1"
    else 
        echo "Fail: $1"
    fi
}

trap "check_exit_code $?" SIGCHLD
mycommand1 &
mycommand2 &
mycommand3 &
...
wait
不幸的是,这只会返回
Success:0
,即使
mycommand#
失败并且其退出代码为
2
,因此我将函数更改为以下内容

#!/bin/sh
set -o monitor

function check_exit_code() {
    local EXIT_STATUS=$? 
    if [ "$EXIT_STATUS" -eq "0" ]
    then 
        echo "Success: $EXIT_STATUS"
    else 
        echo "Fail: $EXIT_STATUS"
    fi
}

trap "check_exit_code" SIGCHLD
mycommand1 &
mycommand2 &
mycommand3 &
...
wait

这只返回
Fail:145
,而
mycommand#
无法返回。我怀疑当我写
$?
时,我收到了另一个命令的退出状态。有什么问题?您将如何修复它?

第一次尝试的问题是
check\u exit\u status$?
周围的双引号。在设置陷阱之前,外壳将
$?
扩展为零,因此,SIGCHLD会触发
检查退出状态0
,无论发生什么情况,因此持续的
成功:0
输出

关于您的第二次尝试,在进入陷阱操作时,特殊参数像往常一样保持最近管道的退出状态,在本例中为
等待
。由于为SIGCHLD设置了陷阱,因此外壳会中断
等待
并分配128 + 17(相当于SIGCHLD的数字)到,在接收到该信号时


使用bash-5.1.4或更新版本,您可以实现如下所示的预期结果:

while true; do
  wait -n -p pid
  case $?,$pid in
  ( 0* ) # a job has exited with zero
    continue ;;
  ( *, ) # pid is empty, no jobs left
    break ;;
  ( *  ) # a job has exited with non-zero
    trap "exit $?" TERM
    kill 0
  esac
done