【问题标题】:Why doesn't bash script wait for its child processes to finish before exiting the parent script on receiving Sigterm?为什么 bash 脚本在接收 Sigterm 时退出父脚本之前不等待其子进程完成?
【发布时间】:2019-12-07 08:47:11
【问题描述】:
trap exit_gracefully TERM

exit_gracefully() {
    echo "start.sh got SIGTERM"
    echo "Sending TERM to child_process_1_pid: ${child_process_1_pid}"
    echo "Sending TERM to child_process_2_pid: ${child_process_2_pid}"
    echo "Sending TERM to child_process_3_pid: ${child_process_3_pid}"
    kill -TERM ${child_process_1_pid} ${child_process_2_pid} ${child_process_3_pid}
}

consul watch -http-addr=${hostIP}:8500 -type=key -key=${consul_kv_key} /child_process_1.sh 2>&1 &
child_process_1_pid=$!

/child_process_2.sh &
child_process_2_pid=$!

/child_process_3.sh &
child_process_3_pid=$!

/healthcheck.sh &

/configure.sh

# sleep 36500d &
# wait $!

wait ${child_process_1_pid} ${child_process_2_pid} ${child_process_3_pid}

echo 'start.sh exiting'

start.sh 是父脚本。当 SIGTERM 被捕获时,它被转发到它的 3 个子进程。如果 # sleep 36500d & #wait $!被注释掉(从代码中去掉),start.sh不等待child_process_1.sh、child_process_2.sh和child_process_3.sh收到SIGTERM,处理完退出后再退出父进程(start.sh),而是 start.sh 在收到 SIGTERM 时立即退出,甚至在子进程可以处理它之前。但是,如果我在代码中保持 sleep 36500d & wait $! 未注释,父进程(start.sh)会等待子进程(1、2 和 3)接收、处理 Sigterm 并先退出退出自己。

为什么在任何一种情况下我都等待 3 个 pid(子进程),但仍然存在这种差异?为什么我在等待 3 个 pid 时需要睡眠?

【问题讨论】:

  • 检查wait返回的值。一般来说,如果它大于 128,那么它会被信号提前终止(通过信号 $? - 128),所以你可能正在寻找类似while wait $pid1 $pid2 $pid3; test $? -ge 128; do : ; done

标签: bash shell sigterm


【解决方案1】:

接收到信号将导致任何正在进行的wait 命令返回。

这是因为信号的目的是中断当前正在执行的进程。

您看到的所有效果都只是当前wait 返回、处理程序运行以及脚本从wait 退出处继续的结果。

【讨论】:

  • 那么,我们可以在exit_gracefully 中添加一个wait(前提是同一个PID 不会再被回收和重用)?
  • 我会一直循环直到wait 成功退出,可能由处理程序设置的标志保护
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-12
  • 2016-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多