如何在 SIGCHLD 子失败时处理错误的退出代码
How to handle wrong exit code upon child failure with SIGCHLD
我有一个 shell 脚本,它在后台生成一堆子进程到 运行。如果其中任何一个失败,我想用 kill -- -$$
.
终止所有子进程和父进程
我试图在父进程中创建一个更简单的信号处理函数 check_exit_code()
以查看它是否可以正常工作。每次子进程终止时都会调用它,使用 trap
和 SIGCHLD
信号。
#!/bin/sh
set -o monitor
function check_exit_code {
if [ -eq "0" ]
then
echo "Success: "
else
echo "Fail: "
fi
}
trap "check_exit_code $?" SIGCHLD
mycommand1 &
mycommand2 &
mycommand3 &
...
wait
不幸的是,这只有 returns 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
这只能returnFail: 145
,mycommand#
不能return。我怀疑当我写 $?
时,我收到了另一个命令的退出状态。问题是什么?你会如何解决它?
您第一次尝试的问题是 check_exit_status $?
周围的双引号。 shell 在设置陷阱之前将 $?
扩展为零,因此 SIGCHLD 无论如何都会触发 check_exit_status 0
,因此常量 Success: 0
输出。
关于您的第二次尝试,在进入陷阱操作时,特殊参数 ? 像往常一样保持最近管道的退出状态,在本例中为 wait
.由于为 SIGCHLD 设置了陷阱,shell 中断 wait
并将 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
我有一个 shell 脚本,它在后台生成一堆子进程到 运行。如果其中任何一个失败,我想用 kill -- -$$
.
我试图在父进程中创建一个更简单的信号处理函数 check_exit_code()
以查看它是否可以正常工作。每次子进程终止时都会调用它,使用 trap
和 SIGCHLD
信号。
#!/bin/sh
set -o monitor
function check_exit_code {
if [ -eq "0" ]
then
echo "Success: "
else
echo "Fail: "
fi
}
trap "check_exit_code $?" SIGCHLD
mycommand1 &
mycommand2 &
mycommand3 &
...
wait
不幸的是,这只有 returns 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
这只能returnFail: 145
,mycommand#
不能return。我怀疑当我写 $?
时,我收到了另一个命令的退出状态。问题是什么?你会如何解决它?
您第一次尝试的问题是 check_exit_status $?
周围的双引号。 shell 在设置陷阱之前将 $?
扩展为零,因此 SIGCHLD 无论如何都会触发 check_exit_status 0
,因此常量 Success: 0
输出。
关于您的第二次尝试,在进入陷阱操作时,特殊参数 ? 像往常一样保持最近管道的退出状态,在本例中为 wait
.由于为 SIGCHLD 设置了陷阱,shell 中断 wait
并将 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