终止后台进程后Bash脚本ps命令末尾报错的原因
问题描述
编写Bash课程作业脚本时出现异常:脚本整体执行流程正常,但在第42行的ps命令输出完成后,会额外弹出错误提示:script.sh: line 42: <PID> Terminated sleep 900 &。预期是ps命令输出干净,kill命令有对应输出,或者错误提示出现在kill命令执行的行,而非ps之后。
相关脚本如下:
#!/bin/bash # Clears screen and displays current running processes clear ps # Pauses for 10 seconds sleep 10 # Displays Parent Process ID using $BASHPID env var (expands to subshells) # $BASHPID requires Bash 4 or later echo echo -e "Parent Process ID: $BASHPID" echo # Creates background process: Pause for 900 seconds sleep 900 & # Displays background jobs jobs -l # Pauses for 10 seconds sleep 10 # Uses jobs -l, grep (in case other jobs are running), and cut to find PID of background job and saves it as a variable bgjob=$(jobs -l | grep "sleep 900" | cut -d" " -f2) # Terminates the background job created kill -SIGTERM $bgjob # Displays current processes so you can verify background job sucsessfully terminated echo ps echo # Pauses for 10 seconds sleep 10 exit 0
解决思路与方案
- 这个延迟出现的提示是Bash的作业通知机制导致的:当后台进程被kill终止后,Bash不会立刻输出终止通知,而是会等到下一个前台命令执行完成后才打印这条信息,所以它会出现在
ps命令输出之后。 - 针对需求,可采用以下几种解决方法:
- 立即处理终止状态:在
kill命令后添加wait $bgjob 2>/dev/null,手动触发Bash处理后台进程的终止状态,这样通知会在kill后立刻输出,不会延迟到ps之后。修改后的代码片段:kill -SIGTERM $bgjob wait $bgjob 2>/dev/null # 处理后台进程终止状态,消除延迟提示 echo ps echo - 关闭作业通知:在脚本开头添加
set +m关闭监控模式,这样Bash会完全禁止后台作业的终止通知输出。但注意这会影响脚本中所有后台作业的状态提示。 - 优化PID获取方式:原脚本通过
jobs -l | grep | cut提取PID的方式不够可靠,建议直接在创建后台进程时保存PID:
这种方式避免了因# 创建后台进程时直接捕获PID sleep 900 & bgjob=$! # $! 指向最后一个启动的后台进程PIDjobs输出格式变化导致的PID提取错误,稳定性更高。
- 立即处理终止状态:在
内容的提问来源于stack exchange,提问作者Aaron
相关产品推荐
相关产品推荐

