#!/bin/bash
################################################################################
# 进程状态检测模块
# 功能: 检测僵尸进程、线程总数、文件描述符使用率、进程TOP列表等
# 作者: Claude Code
# 日期: 2026-05-09
################################################################################

# 获取脚本所在目录并加载依赖
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LIB_DIR="${LIB_DIR:-/tmp/check_modules}"

# 加载配置文件和通用函数库
if [ -f "$LIB_DIR/lib/config.sh" ]; then
    source "$LIB_DIR/lib/config.sh"
else
    echo "ERROR: 配置文件不存在: $LIB_DIR/lib/config.sh"
    exit 1
fi

if [ -f "$LIB_DIR/lib/common.sh" ]; then
    source "$LIB_DIR/lib/common.sh"
else
    echo "ERROR: 通用函数库不存在: $LIB_DIR/lib/common.sh"
    exit 1
fi

# ==================== 检测函数 ====================

# 检测僵尸进程
check_zombie_processes() {
    local zombie_count=0

    # 统计僵尸进程数量
    zombie_count=$(ps -eo stat,pid,ppid,comm --no-headers 2>/dev/null | grep -c " Z" || echo "0")

    output_result "ZOMBIE_COUNT" "$zombie_count"

    if [ "$zombie_count" -gt 0 ]; then
        output_result "ZOMBIE_STATUS" "严重"
        echo "ERROR:检测到${zombie_count}个僵尸进程"
    else
        output_result "ZOMBIE_STATUS" "正常"
    fi
}

# 检测线程总数
check_thread_count() {
    local thread_count=0
    local status

    # 统计线程总数
    thread_count=$(ps -eLf --no-headers 2>/dev/null | wc -l)

    # 判断状态
    if [ "$thread_count" -ge $THREAD_CRITICAL ]; then
        status="严重"
    elif [ "$thread_count" -ge $THREAD_WARNING ]; then
        status="警告"
    else
        status="正常"
    fi

    output_result "THREAD_COUNT" "$thread_count"
    output_result "THREAD_STATUS" "$status"

    if [ "$status" != "正常" ]; then
        echo "ERROR:线程总数过多: ${thread_count}"
    fi
}

# 检测文件描述符使用率
check_file_descriptors() {
    local allocated maximum usage_percent status

    # 从 /proc/sys/fs/file-nr 读取文件描述符信息
    # 格式: allocated-free maximum
    read allocated free maximum < <(cat /proc/sys/fs/file-nr 2>/dev/null)

    if [ -n "$maximum" ] && [ "$maximum" -gt 0 ]; then
        usage_percent=$(awk "BEGIN {printf \"%.1f\", ($allocated / $maximum) * 100}")

        # 判断状态
        if (( $(awk "BEGIN {print ($usage_percent >= 90)}") )); then
            status="严重"
        elif (( $(awk "BEGIN {print ($usage_percent >= 80)}") )); then
            status="警告"
        else
            status="正常"
        fi

        output_result "FD_ALLOCATED" "$allocated"
        output_result "FD_MAXIMUM" "$maximum"
        output_result "FD_USAGE" "${usage_percent}%"
        output_result "FD_STATUS" "$status"

        if [ "$status" != "正常" ]; then
            echo "ERROR:文件描述符使用率过高: ${usage_percent}%"
        fi
    else
        output_result "FD_STATUS" "未知"
    fi
}

# 检测系统负载
check_system_load() {
    local load1 load5 load15
    local cpu_cores

    # 从 /proc/loadavg 读取负载
    read load1 load5 load15 rest < /proc/loadavg

    # 获取CPU核心数
    cpu_cores=$(nproc)

    # 计算负载比例
    local load_ratio=$(awk "BEGIN {printf \"%.2f\", $load1 / $cpu_cores}")

    output_result "LOAD_1MIN" "$load1"
    output_result "LOAD_5MIN" "$load5"
    output_result "LOAD_15MIN" "$load15"
    output_result "LOAD_CORES" "$cpu_cores"
    output_result "LOAD_RATIO" "$load_ratio"

    # 判断负载状态
    local load_status
    if (( $(awk "BEGIN {print ($load1 >= $cpu_cores * 2)}") )); then
        load_status="严重"
    elif (( $(awk "BEGIN {print ($load1 >= $cpu_cores)}") )); then
        load_status="警告"
    else
        load_status="正常"
    fi

    output_result "LOAD_STATUS" "$load_status"

    if [ "$load_status" != "正常" ]; then
        echo "ERROR:系统负载过高: ${load1} (核心数: ${cpu_cores})"
    fi
}

# 检测进程CPU TOP10
check_process_top_cpu() {
    local top10

    top10=$(ps -eo pid,comm,%cpu,%mem --no-headers 2>/dev/null | sort -k3 -rn | head -10)

    if [ -n "$top10" ]; then
        # 格式化输出
        local formatted=""
        while IFS= read -r line; do
            if [ -n "$line" ]; then
                if [ -n "$formatted" ]; then
                    formatted="${formatted}; ${line}"
                else
                    formatted="${line}"
                fi
            fi
        done <<< "$top10"

        output_result "PROCESS_TOP10_CPU" "$formatted"
    else
        output_result "PROCESS_TOP10_CPU" "获取失败"
    fi
}

# 检测进程内存 TOP10
check_process_top_memory() {
    local top10

    top10=$(ps -eo pid,comm,%mem,%cpu --no-headers 2>/dev/null | sort -k3 -rn | head -10)

    if [ -n "$top10" ]; then
        # 格式化输出
        local formatted=""
        while IFS= read -r line; do
            if [ -n "$line" ]; then
                if [ -n "$formatted" ]; then
                    formatted="${formatted}; ${line}"
                else
                    formatted="${line}"
                fi
            fi
        done <<< "$top10"

        output_result "PROCESS_TOP10_MEMORY" "$formatted"
    else
        output_result "PROCESS_TOP10_MEMORY" "获取失败"
    fi
}

# 检测进程总数
check_process_count() {
    local process_count

    process_count=$(ps aux --no-headers 2>/dev/null | wc -l)

    output_result "PROCESS_COUNT" "$process_count"
}

# 检测运行时间最长的进程
check_longest_running() {
    local longest

    longest=$(ps -eo pid,comm,etime --no-headers 2>/dev/null | sort -k3 -rn | head -5)

    if [ -n "$longest" ]; then
        output_result "PROCESS_LONGEST_RUNNING" "已获取"
    else
        output_result "PROCESS_LONGEST_RUNNING" "获取失败"
    fi
}

# 检测D状态不可中断睡眠进程
check_uninterruptible_processes() {
    local d_count=0
    local d_processes=""

    # 统计D状态进程
    d_processes=$(ps -eo stat,pid,comm --no-headers 2>/dev/null | grep " D" | head -10)
    d_count=$(echo "$d_processes" | wc -l)

    if [ -n "$d_processes" ]; then
        d_processes=$(echo "$d_processes" | tr '\n' ',' | sed 's/,$//')
    fi

    output_result "UNINTERRUPTIBLE_COUNT" "$d_count"

    if [ -n "$d_processes" ]; then
        output_result "UNINTERRUPTIBLE_PROCESSES" "$d_processes"
    fi

    if [ "$d_count" -gt 5 ]; then
        output_result "UNINTERRUPTIBLE_STATUS" "严重"
    elif [ "$d_count" -gt 0 ]; then
        output_result "UNINTERRUPTIBLE_STATUS" "警告"
    else
        output_result "UNINTERRUPTIBLE_STATUS" "正常"
    fi
}

# 按进程统计打开文件数TOP5
check_process_open_files_top5() {
    if command -v lsof &> /dev/null; then
        local top5
        top5=$(lsof 2>/dev/null | awk '{print $2}' | sort | uniq -c | sort -rn | head -5)

        if [ -n "$top5" ]; then
            output_result "PROCESS_OPEN_FILES_TOP5" "$top5"
        else
            output_result "PROCESS_OPEN_FILES_TOP5" "无数据"
        fi
    else
        output_result "PROCESS_OPEN_FILES_TOP5" "lsof不可用"
    fi
}

# 按进程统计网络连接数TOP5
check_process_connections_top5() {
    if command -v ss &> /dev/null; then
        local top5
        # 获取各进程的网络连接数
        top5=$(ss -ntp 2>/dev/null | awk '{print $7}' | sort | uniq -c | sort -rn | head -5 | grep -v "PID")

        if [ -n "$top5" ]; then
            output_result "PROCESS_CONNECTIONS_TOP5" "$top5"
        else
            output_result "PROCESS_CONNECTIONS_TOP5" "无数据"
        fi
    else
        output_result "PROCESS_CONNECTIONS_TOP5" "ss不可用"
    fi
}

# 检测进程可执行文件路径
check_process_executable_paths() {
    if command -v ps &> /dev/null; then
        # 获取TOP10进程的可执行文件路径
        local exe_paths=""
        exe_paths=$(ps -eo pid,comm,exe --no-headers 2>/dev/null | sort -k3 -rn | head -10 | awk '{print $1":"$2":"$3}' | tr '\n' ',' | sed 's/,$//')

        if [ -n "$exe_paths" ]; then
            output_result "PROCESS_EXE_PATHS_TOP10" "$exe_paths"
        else
            output_result "PROCESS_EXE_PATHS_TOP10" "无数据"
        fi

        # 统计孤儿进程
        local orphan_count=0
        orphan_count=$(ps -eo pid,ppid,comm --no-headers 2>/dev/null | awk '$2==1 {print $1}' | wc -l)
        output_result "PROCESS_ORPHAN_COUNT" "$orphan_count"

        if [ "$orphan_count" -gt 10 ]; then
            output_result "PROCESS_ORPHAN_STATUS" "严重"
        elif [ "$orphan_count" -gt 0 ]; then
            output_result "PROCESS_ORPHAN_STATUS" "警告"
        else
            output_result "PROCESS_ORPHAN_STATUS" "正常"
        fi
    else
        output_result "PROCESS_EXE_PATHS_TOP10" "ps不可用"
    fi
}

# ==================== 主检测流程 ====================
main() {
    log_info "开始进程状态检测..."

    # 执行各项检测
    check_zombie_processes
    check_thread_count
    check_file_descriptors
    check_system_load
    check_process_count
    check_process_top_cpu
    check_process_top_memory
    check_longest_running
    check_uninterruptible_processes
    check_process_open_files_top5
    check_process_connections_top5
    check_process_executable_paths

    log_info "进程状态检测完成"
}

# 执行主函数
main
