Unix并行处理中进程以退出码145退出的排查方案咨询
子进程批量执行后退出码145排查指南
环境信息
$ cat /etc/redhat-release Red Hat Enterprise Linux release 8.6 (Ootpa) $ uname -a Linux srvr51 4.18.0-372.16.1.el8_6.x86_64 #1 SMP Tue Jun 28 03:02:21 EDT 2022 x86_64 x86_64 x86_64 GNU/Linux $ ksh --version version sh (AT&T Research) 93u+ 2012-08-01 $ echo $KSH_VERSION Version AJM 93u+ 2012-08-01 $ uname -mrs Linux 4.18.0-372.16.1.el8_6.x86_64 x86_64
父进程子进程处理代码
信号处理与子进程状态监控
res=0 handle_chld() { local tmp=() for i in ${!pids[@]}; do if [ ! -d /proc/${pids[i]} ]; then wait ${pids[i]} ret_cd=`echo $?` if [ $ret_cd -ne 0 ]; then res=$ret_cd fi echo "Stopped ${pids[i]}; exit code: $ret_cd" >> ${logfile} STATUS+=($ret_cd) unset pids[i] fi done } set -o monitor trap "handle_chld" CHLD
启动子进程(共9个数据加载脚本)
sh filepath/script1.sh params tmp=$! pids+=($tmp) # ... 中间省略script2到script8的启动代码 sh filepath/script9.sh params tmp=$! pids+=($tmp)
等待所有子进程完成
while [ ${#pids[@]} -gt 0 ]; do echo "WAITING FOR: ${pids[@]}" >> ${logfile} sleep 1; done
日志现象
所有数据已成功加载到目标表,但仅script1.sh对应进程退出码为0,其余8个进程均返回退出码145:
WAITING FOR: 3034365 3034367 3034368 3034369 3034370 3034374 3034379 3034393 3034401 WAITING FOR: 3034365 3034367 3034368 3034369 3034370 3034374 3034379 3034393 3034401 WAITING FOR: 3034365 3034367 3034368 3034369 3034370 3034374 3034379 3034393 3034401 WAITING FOR: 3034365 3034367 3034368 3034369 3034370 3034374 3034379 3034393 3034401 WAITING FOR: 3034365 3034367 3034368 3034369 3034370 3034374 3034379 3034393 3034401 Stopped 3034370; exit code: 0 WAITING FOR: 3034365 3034367 3034368 3034369 3034374 3034379 3034393 3034401 Stopped 3034365; exit code: 145 Stopped 3034369; exit code: 145 Stopped 3034374; exit code: 145 WAITING FOR: 3034367 3034368 3034379 3034393 3034401 Stopped 3034393; exit code: 145 Stopped 3034401; exit code: 145 WAITING FOR: 3034367 3034368 3034379 Stopped 3034368; exit code: 145 Stopped 3034367; exit code: 145 WAITING FOR: 3034379 WAITING FOR: 3034379 WAITING FOR: 3034379 WAITING FOR: 3034379 WAITING FOR: 3034379 WAITING FOR: 3034379 WAITING FOR: 3034379 WAITING FOR: 3034379 WAITING FOR: 3034379 Stopped 3034379; exit code: 145
下一步排查方向
验证子脚本单独执行的退出码
逐个执行sh filepath/scriptX.sh params; echo $?(X从2到9),确认脚本自身是否返回145,还是仅在父进程批量启动时出现该问题。解析退出码145的真实含义
Linux中退出码>128时,通常表示进程被信号终止:145-128=17,对应信号SIGCHLD。但SIGCHLD是子进程结束时通知父进程的信号,不会直接终止子进程,需进一步排查:- 检查子脚本内部是否有主动返回145的逻辑(如
exit 145或return 145) - 查看系统日志(
journalctl -xe或/var/log/messages),确认是否有其他进程向子进程发送信号17
- 检查子脚本内部是否有主动返回145的逻辑(如
排查父进程信号处理逻辑的问题
- 当前逻辑通过遍历
/proc目录判断子进程是否存活,存在时间差,可能导致wait获取的状态不准确。尝试修改handle_chld函数,改用wait -n(ksh支持)直接等待任意子进程退出,避免遍历/proc:handle_chld() { while true; do wait -n local ret_cd=$? if [ $ret_cd -eq 0 ]; then continue elif [ $ret_cd -gt 128 ]; then # 进程被信号终止,可进一步处理 ret_cd=$((ret_cd-128)) fi # 匹配退出的PID并更新pids数组、日志等逻辑 # ... 原有日志和状态更新代码 done } - 尝试移除
set -o monitor,观察是否还会出现相同问题。
- 当前逻辑通过遍历
验证shell版本兼容性
ksh93u+ 2012-08-01在RHEL8.6上可能存在子进程信号处理的bug,尝试用bash替代ksh执行父脚本,对比结果。检查资源限制
虽然数据加载成功,但需确认子进程是否遇到资源限制(如内存、文件句柄)导致异常退出:- 执行
ulimit -a查看父进程的资源限制 - 在子脚本中添加
ulimit -a >> 子脚本日志文件,记录运行时的资源限制
- 执行
内容的提问来源于stack exchange,提问作者Shashank Shekhar
相关产品推荐
相关产品推荐

