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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 14:38:15