Linux Bash中killProc函数杀死部分进程时出现异常输出问题排查
解决kill进程后出现意外Killed输出的问题
系统环境
Linux <server_alias> 3.10.0-1160.76.1.el7.x86_64 #1 SMP Tue Jul 26 14:15:37 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
问题场景
我编写了killProc函数用于通过进程名终止指定进程,代码如下:
killProc () { local PROCNAME="$1" echo "$(date) | Attempting to shutdown $PROCNAME ... " if [[ -z $(findproc "$PROCNAME") ]]; then echo "Process not running ..." else # 基于进程名查找PID local PROCESS_ID=$( ps -ef -u ${USER} | grep "${APPNAME}" | grep -v grep | grep "procname ${PROCNAME}" | awk '{print $2}') # 仅当找到PID时执行杀进程操作 if [[ "$PROCESS_ID" ]]; then set -x kill -9 "$PROCESS_ID" # 检查进程是否被成功杀死 temp_exit=$? if [ $temp_exit -eq 0 ]; then while kill -0 ${PROCESS_ID} 2>/dev/null; do echo "$(date) | Waiting for process to stop running ... " sleep 2 done echo "Done" else echo "Failed" fi set +x else echo "Missing" fi fi }
ps命令输出示例:
<USER> 7456 0.3 0.0 77112 9268 pts/0 S 16:29 0:00 <path> -proctype dis -procname procname1 <params> -p 10000
异常现象
该函数对大部分进程有效,但针对部分进程执行时,在sleep 2后会出现意外输出:
Wed Mar 20 16:20:13 UTC 2024 | Attempting to shutdown procname1 ... + kill -9 6603 + temp_exit=0 + '[' 0 -eq 0 ']' + kill -0 6603 ++ date + echo 'Wed Mar 20 16:20:13 UTC 2024 | Waiting for process to stop running ... ' Wed Mar 20 16:20:13 UTC 2024 | Waiting for process to stop running ... + sleep 2 <path>/bin/killProcs.sh: line 26: 6603 Killed taskset -c 39,40 <path> <params> -procname procname1 -p 10001 < /dev/null > ${LOG}/dis_test_nont_$(date +%s).log 2>&1 + kill -0 6603 + echo Done Done
已尝试给kill -9 "$PROCESS_ID"添加2> /dev/null重定向错误输出,但无效;即使移除函数内部分代码,问题仍偶发出现,且仅部分进程受影响。
原因分析
这个Killed输出并非来自kill命令本身的标准错误,而是执行脚本的bash进程在监控子进程状态时主动打印的消息。当被杀死的进程是当前shell的子进程时,bash会在标准错误输出这条状态信息,因此单独给kill命令加重定向无法屏蔽它。
解决方案
方案1:调用函数时重定向整体stderr
如果可以接受屏蔽函数内所有错误输出,调用时直接重定向:
killProc procname1 2>/dev/null
方案2:让目标进程脱离当前shell会话
如果这些进程是通过当前脚本启动的,启动时使用nohup或setsid让进程脱离当前shell的会话组,bash就不会再监控其状态:
nohup taskset -c 39,40 <path> <params> -procname procname1 -p 10001 < /dev/null > ${LOG}/dis_test_nont_$(date +%s).log 2>&1 &
方案3:函数内临时重定向并恢复stderr
如果需要保留set -x等其他错误输出,可临时保存并重定向stderr:
killProc () { local PROCNAME="$1" echo "$(date) | Attempting to shutdown $PROCNAME ... " if [[ -z $(findproc "$PROCNAME") ]]; then echo "Process not running ..." else local PROCESS_ID=$( ps -ef -u ${USER} | grep "${APPNAME}" | grep -v grep | grep "procname ${PROCNAME}" | awk '{print $2}') if [[ "$PROCESS_ID" ]]; then # 保存当前stderr到文件描述符3 exec 3>&2 # 临时重定向stderr到/dev/null,屏蔽bash的子进程状态输出 exec 2>/dev/null set -x kill -9 "$PROCESS_ID" temp_exit=$? if [ $temp_exit -eq 0 ]; then while kill -0 ${PROCESS_ID} 2>/dev/null; do echo "$(date) | Waiting for process to stop running ... " sleep 2 done echo "Done" else echo "Failed" fi set +x # 恢复原stderr并关闭临时文件描述符 exec 2>&3 exec 3>&- else echo "Missing" fi fi }
内容的提问来源于stack exchange,提问作者user06931912
相关产品推荐
相关产品推荐

