You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌套函数并发出错时Shell脚本未退出的解决需求(bash4.2无wait-n)

问题:并发子进程出错时Shell脚本未终止

你的Shell脚本在多个嵌套函数并发执行出错时,不会终止仍继续运行。示例代码如下:

status() {
    exit_st=$1
    error_1=$2
    if ! [[ $exit_st -eq 0 ]]; then
        echo "[ERROR] -  ${error_1}"
        exit 1
    else 
        echo "[INFO] -  ${error_1}"
    fi
}

abc(){
   val1= $1
   val2= $2
   #Some SQL command here
   status $? "SQL command step"
}

abc cmd1 cmd2 &

abc cmd3 cmd4 &

wait 

echo 'hi'

当#Some SQL command here处的命令执行失败时,脚本并未退出,反而继续执行并打印hi。将status函数中的exit改为return也无法实现脚本出错退出的效果。需求是:只要任意abc子进程执行失败,整个脚本就以非零状态码退出。注意使用的是GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)版本,无法使用wait -n选项。

原因分析

  1. 子进程中执行exit 1只会终止当前子进程,不会影响父脚本的运行,父脚本仍会等待所有子进程完成后继续执行。
  2. 改为return只是让abc函数返回非零值,但子进程本身的退出状态会保留这个值,可父脚本的wait默认只会等待所有子进程结束,不会因为某个子进程失败而主动终止。
  3. 原脚本中val1= $1和val2= $2存在语法错误,变量赋值时等号前后不能有空格,会导致执行报错。

解决方案

通过记录每个子进程的PID,逐个等待并检查退出状态,一旦发现非零状态码,立即终止脚本并杀死剩余未完成的子进程。修改后的脚本如下:

# 存储子进程PID的数组
declare -a pids

status() {
    exit_st=$1
    error_1=$2
    if ! [[ $exit_st -eq 0 ]]; then
        echo "[ERROR] -  ${error_1}"
        exit 1
    else 
        echo "[INFO] -  ${error_1}"
    fi
}

abc(){
   val1="$1"
   val2="$2"
   # 替换为实际SQL命令,此处用false模拟执行失败
   false
   status $? "SQL command step for $val1 $val2"
}

# 启动子进程并记录PID
abc cmd1 cmd2 &
pids+=($!)

abc cmd3 cmd4 &
pids+=($!)

# 遍历PID数组,逐个检查子进程状态
for pid in "${pids[@]}"; do
    wait "$pid"
    exit_code=$?
    if [[ $exit_code -ne 0 ]]; then
        echo "[FATAL] - 子进程PID $pid 执行失败,终止脚本"
        # 杀死剩余运行中的子进程
        for remaining_pid in "${pids[@]}"; do
            if kill -0 "$remaining_pid" 2>/dev/null; then
                kill "$remaining_pid"
                echo "[INFO] - 已终止子进程PID $remaining_pid"
            fi
        done
        exit "$exit_code"
    fi
done

# 所有子进程成功才执行后续代码
echo 'hi'

关键说明

  1. 用数组pids存储每个后台子进程的PID($!表示最后一个后台进程的PID)。
  2. 逐个wait每个PID,检查其退出状态:
    • 若某个子进程退出状态非零,立即打印错误信息。
    • 用kill -0检查剩余PID对应的进程是否还在运行,若存在则杀死,避免无效执行。
    • 最后以该子进程的退出状态码终止整个脚本。
  3. 修复了变量赋值的语法错误,确保参数正常传递。

内容的提问来源于stack exchange,提问作者dijeah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 11:08:19