Bash – 监听后台进程的退出

Bash – 监听后台进程的退出

我有这个 bash 脚本来启动一些服务器:

services=(
    account-service
    reminder-service
    activity-service
    socket-service
    chat-service
    web-app
)


for s in "${services[@]}"; do

 (
   set -e;
   cd "$s"
   git pull
   npm start || exit 1 # always fails
 ) &

 sleep 1;

done

wait;

有时该git pull命令会失败。但故障深深地存在于日志中,而且并不总是显而易见。如果子 shell 中的命令之一以 1 退出,如何中止整个脚本?

答案1

嗯,也许:将wait语句更改为:

while true; do
    wait -n || exit 1          # if one of the background jobs failed, abort
    [[ "$(jobs)" ]] && break   # exit this loop if no more jobs
done

完全未经测试。我不确定jobs在非交互式 shell 中是否按预期工作。

答案2

这里有几个问题:

  1. 如果子 shell 中的命令失败,则使整个脚本中止。
  2. 提高发生的任何错误的可见性。

我将从第二个开始。该问题包含答案的种子:记录错误,但日志的内容对用户来说并不明显。因此,记录错误(在临时日志文件中)并在最后显示它们:

服务=(
    账户服务
    提醒服务
    活动服务
    套接字服务
    聊天服务
    网络应用程序
错误文件=$(mktemp)

对于“${services[@]}”中的 s;做
   设置-e;
   cd“$s”
   git拉  || {
        回声“$s”>>“$errfile”
        1号出口
   }
   回声“$cmd”|巴什
 ) &
 睡觉 1
完毕

等待

if [ -s "$errfile" ]
然后
        echo“以下服务有错误:”
        猫“$errfile”
rm -f "$errfile"

解决问题 #1 的最简单方法是定期检查子 shell 中的代码[ -s "$errfile" ],并在出现任何问题时中止自身。一个更雄心勃勃的方法是让主(父)进程跟踪子进程的 PID 并向它们发送信号。我不确定如果没有wait -n. (也许您可以让有错误的子级向父级发送信号以将其从wait. 中打破。)

相关内容