Bash:为什么过早等待 returns 代码 145
Bash: why wait returns prematurely with code 145
这个问题很奇怪,我在网上找不到任何关于这个的文档。在下面的代码片段中,我只是试图 运行 一堆并行的子进程,在它们退出时打印一些东西,并在最后 collect/print 它们的退出代码。我发现,如果没有捕捉到 SIGCHLD,事情就会像我预期的那样工作,但是,当我捕捉到信号时,事情就会中断。这是代码:
#!/bin/bash
#enabling job control
set -m
cmd_array=( "$@" ) #array of commands to run in parallel
cmd_count=$# #number of commands to run
cmd_idx=0; #current index of command
cmd_pids=() #array of child proc pids
trap 'echo "Child job existed"' SIGCHLD #setting up signal handler on SIGCHLD
#running jobs in parallel
while [ $cmd_idx -lt $cmd_count ]; do
cmd=${cmd_array[$cmd_idx]} #retreiving the job command as a string
eval "$cmd" &
cmd_pids[$cmd_idx]=$! #keeping track of the job pid
echo "Job #$cmd_idx launched '$cmd']"
(( cmd_idx++ ))
done
#all jobs have been launched, collecting exit codes
idx=0
for pid in "${cmd_pids[@]}"; do
wait $pid
child_exit_code=$?
if [ $child_exit_code -ne 0 ]; then
echo "ERROR: Job #$idx failed with return code $child_exit_code. [job_command: '${cmd_array[$idx]}']"
fi
(( idx++ ))
done
当您尝试 运行 以下命令时,您会发现有问题:
./parallel_script.sh "sleep 20; echo done_20" "sleep 3; echo done_3"
这里有趣的是,一旦信号处理程序被调用(当睡眠 3 完成时),等待(正在等待睡眠 20)立即被 return 代码 145。即使在脚本完成后,我也可以看出 sleep 20 仍然是 运行ning。
我无法从 wait 中找到有关此类 return 代码的任何文档。任何人都可以阐明这里发生了什么吗?
(顺便说一句,如果我在等待时添加一个while循环并在return代码为145时继续等待,我实际上得到了我期望的结果)
感谢@muru,我能够使用更少的代码重现 "problem",如下所示:
#!/bin/bash
set -m
trap "echo child_exit" SIGCHLD
function test() {
sleep
echo "'sleep ' just returned now"
}
echo sleeping for 6 seconds in the background
test 6 &
pid=$!
echo sleeping for 2 second in the background
test 2 &
echo waiting on the 6 second sleep
wait $pid
echo "wait return code: $?"
如果你运行这个你会得到以下输出:
linux:~$ sh test2.sh
sleeping for 6 seconds in the background
sleeping for 2 second in the background
waiting on the 6 second sleep
'sleep 2' just returned now
child_exit
wait return code: 145
lunux:~$ 'sleep 6' just returned now
解释:
正如@muru 指出的那样“当命令终止于编号为 N 的致命信号时,Bash 使用值 128+N 作为退出状态。 “(c.f。Bash manual on Exit Status)。
现在误导我的是 "fatal" 信号。我一直在寻找一个在某处失败的命令,但什么也没做。
在 Bash manual on Signals 中更深入地挖掘:“当 Bash 通过 wait 内置函数等待异步命令时,接收到一个陷阱的信号set 将导致等待内置函数立即 return,退出状态大于 128,之后立即执行陷阱。"
好了,上面的脚本中发生的事情如下:
sleep 6
在后台启动
sleep 3
在后台启动
wait
开始等待 sleep 6
sleep 3
终止并且 SIGCHLD 陷阱如果触发中断等待,returns 128 + SIGCHLD = 145
- 我的脚本退出,因为它不再等待
- 后台
sleep 6
终止,因此在脚本已经退出 之后“'sleep 6' 刚刚 returned”
这个问题很奇怪,我在网上找不到任何关于这个的文档。在下面的代码片段中,我只是试图 运行 一堆并行的子进程,在它们退出时打印一些东西,并在最后 collect/print 它们的退出代码。我发现,如果没有捕捉到 SIGCHLD,事情就会像我预期的那样工作,但是,当我捕捉到信号时,事情就会中断。这是代码:
#!/bin/bash
#enabling job control
set -m
cmd_array=( "$@" ) #array of commands to run in parallel
cmd_count=$# #number of commands to run
cmd_idx=0; #current index of command
cmd_pids=() #array of child proc pids
trap 'echo "Child job existed"' SIGCHLD #setting up signal handler on SIGCHLD
#running jobs in parallel
while [ $cmd_idx -lt $cmd_count ]; do
cmd=${cmd_array[$cmd_idx]} #retreiving the job command as a string
eval "$cmd" &
cmd_pids[$cmd_idx]=$! #keeping track of the job pid
echo "Job #$cmd_idx launched '$cmd']"
(( cmd_idx++ ))
done
#all jobs have been launched, collecting exit codes
idx=0
for pid in "${cmd_pids[@]}"; do
wait $pid
child_exit_code=$?
if [ $child_exit_code -ne 0 ]; then
echo "ERROR: Job #$idx failed with return code $child_exit_code. [job_command: '${cmd_array[$idx]}']"
fi
(( idx++ ))
done
当您尝试 运行 以下命令时,您会发现有问题:
./parallel_script.sh "sleep 20; echo done_20" "sleep 3; echo done_3"
这里有趣的是,一旦信号处理程序被调用(当睡眠 3 完成时),等待(正在等待睡眠 20)立即被 return 代码 145。即使在脚本完成后,我也可以看出 sleep 20 仍然是 运行ning。 我无法从 wait 中找到有关此类 return 代码的任何文档。任何人都可以阐明这里发生了什么吗?
(顺便说一句,如果我在等待时添加一个while循环并在return代码为145时继续等待,我实际上得到了我期望的结果)
感谢@muru,我能够使用更少的代码重现 "problem",如下所示:
#!/bin/bash
set -m
trap "echo child_exit" SIGCHLD
function test() {
sleep
echo "'sleep ' just returned now"
}
echo sleeping for 6 seconds in the background
test 6 &
pid=$!
echo sleeping for 2 second in the background
test 2 &
echo waiting on the 6 second sleep
wait $pid
echo "wait return code: $?"
如果你运行这个你会得到以下输出:
linux:~$ sh test2.sh
sleeping for 6 seconds in the background
sleeping for 2 second in the background
waiting on the 6 second sleep
'sleep 2' just returned now
child_exit
wait return code: 145
lunux:~$ 'sleep 6' just returned now
解释:
正如@muru 指出的那样“当命令终止于编号为 N 的致命信号时,Bash 使用值 128+N 作为退出状态。 “(c.f。Bash manual on Exit Status)。 现在误导我的是 "fatal" 信号。我一直在寻找一个在某处失败的命令,但什么也没做。
在 Bash manual on Signals 中更深入地挖掘:“当 Bash 通过 wait 内置函数等待异步命令时,接收到一个陷阱的信号set 将导致等待内置函数立即 return,退出状态大于 128,之后立即执行陷阱。"
好了,上面的脚本中发生的事情如下:
sleep 6
在后台启动sleep 3
在后台启动wait
开始等待sleep 6
sleep 3
终止并且 SIGCHLD 陷阱如果触发中断等待,returns 128 + SIGCHLD = 145- 我的脚本退出,因为它不再等待
- 后台
sleep 6
终止,因此在脚本已经退出 之后“'sleep 6' 刚刚 returned”