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

Shell脚本退出时无法终止nc进程的问题排查

问题分析

你的脚本出现nc进程残留的原因主要有三点:

  1. PID跟踪错误:honeypot_pid+=($!)获取的是后台运行的while循环进程PID,而非nc进程的PID,导致ctrl_c函数无法精准杀死nc。
  2. 子进程脱离父进程:nc运行在子shell中,当脚本主进程退出后,nc会成为孤儿进程被系统初始化进程接管,不会随脚本终止而退出。
  3. nc监听状态特性:处于监听状态的nc不会主动响应父进程的终止信号,只有当客户端断开连接时才会自行退出。
修复方案

以下两种方案都能解决问题,按需选择:

方案一:精准跟踪nc进程PID

修改server函数,直接记录nc的PID,确保终止时能精准查杀:

# Netcat server
server ()
{
    while true; do
        # 单独输出日志头,避免子shell层级
        echo -e "--------" $(date) "--------\n" >> honeypot.log 2>&1
        # 后台运行nc并记录PID
        nc -vnlp $port < banner.txt >> honeypot.log 2>&1 &
        local nc_pid=$!
        honeypot_pid+=($nc_pid)
        # 等待当前nc进程结束后,再启动下一次监听
        wait $nc_pid
    done &
}

同时简化ctrl_c函数,直接杀死记录的nc进程:

function ctrl_c()
{
    echo -e "\nEncerrando o servidor..."
    # 杀死所有记录的nc进程,忽略已终止进程的错误输出
    for pid in "${honeypot_pid[@]}"; do
        kill "$pid" 2>/dev/null
    done
    exit 1
}

方案二:通过进程组批量查杀

利用进程组特性,一次性杀死脚本及其所有子进程(包括nc),无需单独跟踪PID:

function ctrl_c()
{
    echo -e "\nEncerrando o servidor..."
    # 杀死当前脚本所在进程组的所有进程,忽略错误输出
    kill -- -$$ 2>/dev/null
    exit 1
}

同时可以简化server函数,去掉不必要的子shell:

# Netcat server
server ()
{
    while true; do
        echo -e "--------" $(date) "--------\n" >> honeypot.log 2>&1
        nc -vnlp $port < banner.txt >> honeypot.log 2>&1
    done &
}

-- -$$表示杀死进程ID为$$(当前脚本PID)的进程组内所有进程,所有由脚本启动的子进程都会被一并终止。

额外优化建议
  • 移除killall honeypot.sh:脚本退出时自身会终止,无需额外查杀,反而可能误杀其他同名脚本。
  • 添加2>/dev/null到kill命令后:避免因进程已终止而输出错误信息,提升脚本运行的整洁性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 12:32:53