提交 6c84387c authored 作者: 陈泽健's avatar 陈泽健

feat(service-monitor): 新增 13 个检测模块(EMQX/Java/Python/Nginx/Nacos/安全合规/系统日志/时间同步/综合诊断/应用日志)

- P1 核心服务: EMQX 基础/深度、Java 应用检测(含进程列表)、Nginx 深度
- P2 辅助服务: Python 应用检测(含进程列表)、Nginx/Nacos 基础、Nacos 深度、应用日志分析
- P3 系统深度: 综合诊断、安全合规、系统日志、时间同步
Co-Authored-By: 's avatarClaude <noreply@anthropic.com>
上级 0ee7ef8d
#!/bin/bash
################################################################################
# EMQX基础检测模块
# 功能: 检测EMQX容器状态、版本、连接数、会话数等
# 作者: Claude Code
# 日期: 2026-07-20
################################################################################
# 获取脚本所在目录并加载依赖
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
# EMQX容器名称
EMQX_CONTAINER="${CONTAINERS[emqx]}"
# ==================== 辅助函数 ====================
# 在EMQX容器中执行命令
emqx_exec() {
docker exec "$EMQX_CONTAINER" $@ 2>/dev/null
}
# ==================== 检测函数 ====================
# 检测EMQX容器状态(使用模糊匹配)
check_emqx_container() {
local container_status="未运行"
local level="严重"
local matched_container=""
if command -v docker &> /dev/null; then
# 尝试精确匹配
matched_container=$(docker ps --format "{{.Names}}" | grep -x "${EMQX_CONTAINER}" | head -1)
# 如果精确匹配失败,尝试模糊匹配
if [ -z "$matched_container" ] && [ -n "$EMQX_CONTAINER" ]; then
matched_container=$(docker ps --format "{{.Names}}" | grep -i "${EMQX_CONTAINER}" | head -1)
fi
if [ -n "$matched_container" ]; then
container_status="运行中 (${matched_container})"
level="正常"
# 更新全局变量
eval "EMQX_CONTAINER='${matched_container}'"
else
# 检查容器是否存在但未运行
matched_container=$(docker ps -a --format "{{.Names}}" | grep -i "${EMQX_CONTAINER}" | head -1)
if [ -n "$matched_container" ]; then
container_status="已停止 (${matched_container})"
level="警告"
fi
fi
fi
output_result "EMQX_CONTAINER_STATUS" "$container_status"
output_result "EMQX_CONTAINER_LEVEL" "$level"
if [ "$level" != "正常" ]; then
return 1
fi
return 0
}
# 检测EMQX版本
check_emqx_version() {
local version=""
version=$(emqx_exec emqx_ctl broker 2>/dev/null | grep "version" | cut -d: -f2 | tr -d ' ')
if [ -n "$version" ]; then
output_result "EMQX_VERSION" "$version"
fi
}
# 检测EMQX状态
check_emqx_status() {
local status="未知"
if emqx_exec emqx_ctl status 2>/dev/null | grep -q "is running\|Node"; then
status="运行中"
output_result "EMQX_STATUS" "$status"
output_result "EMQX_STATUS_LEVEL" "正常"
else
status="异常"
output_result "EMQX_STATUS" "$status"
output_result "EMQX_STATUS_LEVEL" "严重"
fi
}
# 检测EMQX客户端连接
check_emqx_clients() {
local client_count=0
client_count=$(emqx_exec emqx_ctl clients list 2>/dev/null | wc -l)
if [ -n "$client_count" ]; then
output_result "EMQX_CLIENTS" "$client_count"
fi
}
# 检测EMQX会话数
check_emqx_sessions() {
local session_count=0
session_count=$(emqx_exec emqx_ctl sessions list 2>/dev/null | wc -l)
if [ -n "$session_count" ]; then
output_result "EMQX_SESSIONS" "$session_count"
fi
}
# 检测EMQX订阅数
check_emqx_subscriptions() {
local sub_count=0
sub_count=$(emqx_exec emqx_ctl subscriptions list 2>/dev/null | wc -l)
if [ -n "$sub_count" ]; then
output_result "EMQX_SUBSCRIPTIONS" "$sub_count"
fi
}
# 检测EMQX主题数
check_emqx_topics() {
local topic_count=0
topic_count=$(emqx_exec emqx_ctl topics list 2>/dev/null | wc -l)
if [ -n "$topic_count" ]; then
output_result "EMQX_TOPICS" "$topic_count"
fi
}
# 检测EMQX路由数
check_emqx_routes() {
local route_count=0
route_count=$(emqx_exec emqx_ctl routes list 2>/dev/null | wc -l)
if [ -n "$route_count" ]; then
output_result "EMQX_ROUTES" "$route_count"
fi
}
# 检测EMQX监听端口
check_emqx_listeners() {
local listeners=""
listeners=$(emqx_exec emqx_ctl listeners list 2>/dev/null | grep "running" | wc -l)
if [ -n "$listeners" ]; then
output_result "EMQX_LISTENERS" "$listeners"
fi
}
# 检测EMQX集群状态
check_emqx_cluster() {
local cluster_status="未知"
if emqx_exec emqx_ctl cluster status 2>/dev/null | grep -q "is running\|Cluster"; then
cluster_status="正常"
else
cluster_status="未配置"
fi
output_result "EMQX_CLUSTER" "$cluster_status"
}
# ==================== 主检测流程 ====================
main() {
log_info "开始EMQX基础检测..."
# 检查容器状态
if ! check_emqx_container; then
log_warn "EMQX容器未运行,跳过其他检测"
return
fi
# 执行各项检测
check_emqx_version
check_emqx_status
check_emqx_clients
check_emqx_sessions
check_emqx_subscriptions
check_emqx_topics
check_emqx_routes
check_emqx_listeners
check_emqx_cluster
log_info "EMQX基础检测完成"
}
# 执行主函数
main
#!/bin/bash
################################################################################
# EMQX深度检测模块
# 功能: 深度检测EMQX连接、订阅、消息统计、集群、性能等
# 作者: Claude Code
# 日期: 2026-07-20
################################################################################
# 获取脚本所在目录并加载依赖
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
# EMQX容器名称
EMQX_CONTAINER="${CONTAINERS[emqx]}"
# ==================== 辅助函数 ====================
# 在EMQX容器中执行命令
emqx_exec() {
docker exec "$EMQX_CONTAINER" $@ 2>/dev/null
}
# ==================== 深度检测函数 ====================
# 检测EMQX详细状态
check_emqx_status_detail() {
local broker_status node_status
broker_status=$(emqx_exec emqx_ctl broker 2>/dev/null)
node_status=$(emqx_exec emqx_ctl status 2>/dev/null)
if [ -n "$broker_status" ]; then
# 提取版本信息
local version
version=$(echo "$broker_status" | grep -i "version" | head -1 | awk '{for(i=2;i<=NF;i++)printf $i" "}')
if [ -n "$version" ]; then
output_result "EMQX_BROKER_VERSION" "$version"
fi
fi
if [ -n "$node_status" ]; then
output_result "EMQX_NODE_STATUS" "运行中"
output_result "EMQX_NODE_LEVEL" "正常"
fi
}
# 检测EMQX客户端详情
check_emqx_clients_detail() {
# 获取客户端总数
local client_count
client_count=$(emqx_exec emqx_ctl clients list 2>/dev/null | wc -l)
if [ -n "$client_count" ]; then
output_result "EMQX_CLIENTS_TOTAL" "$client_count"
fi
# 获取连接状态统计
local clients_connected clients_disconnected
clients_connected=$(emqx_exec emqx_ctl clients list 2>/dev/null | grep -c "connected" || echo "0")
if [ -n "$clients_connected" ]; then
output_result "EMQX_CLIENTS_CONNECTED" "$clients_connected"
clients_disconnected=$((client_count - clients_connected))
output_result "EMQX_CLIENTS_DISCONNECTED" "$clients_disconnected"
fi
# 获取最大客户端连接数配置
local max_clients_config
max_clients_config=$(emqx_exec emqx_ctl listeners list 2>/dev/null | grep -E "max_connections" | awk '{print $NF}' | head -1)
if [ -z "$max_clients_config" ] || [ "$max_clients_config" = "0" ]; then
max_clients_config="infinity"
fi
if [ -n "$max_clients_config" ]; then
output_result "EMQX_MAX_CLIENTS" "$max_clients_config"
fi
}
# 检测EMQX订阅详情
check_emqx_subscriptions_detail() {
# 获取订阅总数
local sub_count
sub_count=$(emqx_exec emqx_ctl subscriptions list 2>/dev/null | wc -l)
if [ -n "$sub_count" ]; then
output_result "EMQX_SUBSCRIPTIONS_TOTAL" "$sub_count"
fi
# 统计各主题订阅数
local top_topics
top_topics=$(emqx_exec emqx_ctl subscriptions list 2>/dev/null | awk '{print $2}' | sort | uniq -c | sort -rn | head -5 | tr '\n' '|' | sed 's/|$//')
if [ -n "$top_topics" ]; then
output_result "EMQX_TOP_TOPICS" "$top_topics"
fi
}
# 检测EMQX消息统计
check_emqx_messages_stats() {
# 获取消息统计
local messages_stats
messages_stats=$(emqx_exec emqx_ctl metrics 2>/dev/null | grep -E "messages" || echo "")
if [ -n "$messages_stats" ]; then
# 提取关键指标
local messages_sent messages_received
messages_sent=$(echo "$messages_stats" | grep "messages.sent" | awk '{print $2}' || echo "0")
messages_received=$(echo "$messages_stats" | grep "messages.received" | awk '{print $2}' || echo "0")
if [ -n "$messages_sent" ]; then
output_result "EMQX_MESSAGES_SENT" "$messages_sent"
fi
if [ -n "$messages_received" ]; then
output_result "EMQX_MESSAGES_RECEIVED" "$messages_received"
fi
fi
}
# 检测EMQX主题详情
check_emqx_topics_detail() {
# 获取主题总数
local topic_count
topic_count=$(emqx_exec emqx_ctl topics list 2>/dev/null | wc -l)
if [ -n "$topic_count" ]; then
output_result "EMQX_TOPICS_TOTAL" "$topic_count"
fi
# 获取TOP5主题
local top5_topics
top5_topics=$(emqx_exec emqx_ctl topics list 2>/dev/null | head -6 | tr '\n' '|' | sed 's/|$//')
if [ -n "$top5_topics" ]; then
output_result "EMQX_TOP5_TOPICS" "$top5_topics"
fi
}
# 检测EMQX路由详情
check_emqx_routes_detail() {
# 获取路由总数
local route_count
route_count=$(emqx_exec emqx_ctl routes list 2>/dev/null | wc -l)
if [ -n "$route_count" ]; then
output_result "EMQX_ROUTES_TOTAL" "$route_count"
fi
}
# 检测EMQX监听器详情
check_emqx_listeners_detail() {
# 获取监听器列表
local listeners
listeners=$(emqx_exec emqx_ctl listeners list 2>/dev/null)
if [ -n "$listeners" ]; then
# 统计监听器数量
local listener_count
listener_count=$(echo "$listeners" | grep -c "running" || echo "0")
if [ -n "$listener_count" ]; then
output_result "EMQX_LISTENERS_COUNT" "$listener_count"
fi
# 提取监听端口信息
local listener_ports
listener_ports=$(echo "$listeners" | grep "running" | awk '{print $4}' | tr '\n' ',' | sed 's/,$//')
if [ -n "$listener_ports" ]; then
output_result "EMQX_LISTENER_PORTS" "$listener_ports"
fi
fi
}
# 检测EMQX集群状态
check_emqx_cluster_detail() {
# 获取集群状态
local cluster_status
cluster_status=$(emqx_exec emqx_ctl cluster status 2>/dev/null)
if [ -n "$cluster_status" ]; then
# 检查是否为集群模式
local is_running_cluster
is_running_cluster=$(echo "$cluster_status" | grep -c "is running" || echo "0")
local is_stopped_cluster
is_stopped_cluster=$(echo "$cluster_status" | grep -c "is stopped" || echo "0")
local total_nodes=$((is_running_cluster + is_stopped_cluster))
if [ "$total_nodes" -gt 1 ]; then
output_result "EMQX_CLUSTER_MODE" "是"
output_result "EMQX_CLUSTER_NODES" "$total_nodes"
else
output_result "EMQX_CLUSTER_MODE" "否(单节点)"
output_result "EMQX_CLUSTER_NODES" "1"
fi
else
output_result "EMQX_CLUSTER_MODE" "否(单节点)"
output_result "EMQX_CLUSTER_NODES" "1"
fi
}
# 检测EMQX连接限制
check_emqx_connection_limits() {
# 获取最大连接数配置
local max_connections
max_connections=$(emqx_exec emqx_ctl listeners list 2>/dev/null | grep "max_connections" | awk '{print $NF}' | head -1)
if [ -n "$max_connections" ]; then
output_result "EMQX_MAX_CONNECTIONS" "$max_connections"
fi
# 获取当前连接数
local current_connections
current_connections=$(emqx_exec emqx_ctl clients list 2>/dev/null | wc -l)
if [ -n "$current_connections" ] && [ -n "$max_connections" ] && [ "$max_connections" != "infinity" ]; then
local conn_percent
conn_percent=$(awk "BEGIN {printf \"%.1f\", ($current_connections * 100) / $max_connections}")
output_result "EMQX_CONN_USAGE" "${conn_percent}%"
# 判断连接使用率
local level="正常"
if (( $(awk "BEGIN {print ($conn_percent > 90)}") )); then
level="严重"
elif (( $(awk "BEGIN {print ($conn_percent > 80)}") )); then
level="警告"
fi
output_result "EMQX_CONN_LEVEL" "$level"
fi
}
# 检测EMQX内存使用
check_emqx_memory() {
# 获取EMQX进程内存使用
local emqx_pid
emqx_pid=$(docker exec "$EMQX_CONTAINER" ps aux 2>/dev/null | grep "beam.smp" | grep -v grep | awk '{print $2}' | head -1)
if [ -n "$emqx_pid" ]; then
local mem_usage
mem_usage=$(docker exec "$EMQX_CONTAINER" ps -p "$emqx_pid" -o %mem --no-headers 2>/dev/null | tr -d ' ')
if [ -n "$mem_usage" ]; then
output_result "EMQX_MEMORY_USAGE" "${mem_usage}%"
fi
fi
}
# 检测EMQX会话详情
check_emqx_sessions_detail() {
# 获取会话总数
local session_count
session_count=$(emqx_exec emqx_ctl sessions list 2>/dev/null | wc -l)
if [ -n "$session_count" ]; then
output_result "EMQX_SESSIONS_TOTAL" "$session_count"
fi
# 统计会话状态
local sessions_active
sessions_active=$(emqx_exec emqx_ctl sessions list 2>/dev/null | grep -c "active" || echo "0")
if [ -n "$sessions_active" ]; then
output_result "EMQX_SESSIONS_ACTIVE" "$sessions_active"
local sessions_inactive=$((session_count - sessions_active))
output_result "EMQX_SESSIONS_INACTIVE" "$sessions_inactive"
fi
}
# 检测EMQX插件状态
check_emqx_plugins() {
# 获取已加载的插件列表
local plugins
plugins=$(emqx_exec emqx_ctl plugins list 2>/dev/null | grep "loaded" | awk '{print $1}' | tr '\n' ',' | sed 's/,$//')
if [ -n "$plugins" ]; then
output_result "EMQX_PLUGINS_LOADED" "$plugins"
fi
# 统计插件数量
local plugin_count
plugin_count=$(emqx_exec emqx_ctl plugins list 2>/dev/null | grep -c "loaded" || echo "0")
if [ -n "$plugin_count" ]; then
output_result "EMQX_PLUGINS_COUNT" "$plugin_count"
fi
}
# 检测EMQX规则引擎状态
check_emqx_rules() {
# 获取规则数量
local rules_count
rules_count=$(emqx_exec emqx_ctl rules list 2>/dev/null | wc -l)
if [ -n "$rules_count" ] && [ "$rules_count" -gt 0 ]; then
output_result "EMQX_RULES_COUNT" "$rules_count"
else
output_result "EMQX_RULES_COUNT" "未启用"
fi
}
# 检测EMQX告警状态
check_emqx_alarms() {
# 获取告警信息
local alarms
alarms=$(emqx_exec emqx_ctl alarms list 2>/dev/null)
if [ -n "$alarms" ]; then
# 统计告警数量
local alarm_count
alarm_count=$(echo "$alarms" | wc -l)
if [ "$alarm_count" -gt 0 ]; then
output_result "EMQX_ALARMS_COUNT" "$alarm_count"
output_result "EMQX_ALARMS_LEVEL" "警告"
# 获取告警详情
local alarm_detail
alarm_detail=$(echo "$alarms" | head -5 | tr '\n' '|' | sed 's/|$//')
output_result "EMQX_ALARMS_DETAIL" "$alarm_detail"
else
output_result "EMQX_ALARMS_COUNT" "0"
output_result "EMQX_ALARMS_LEVEL" "正常"
fi
else
output_result "EMQX_ALARMS_COUNT" "0"
output_result "EMQX_ALARMS_LEVEL" "正常"
fi
}
# 检测EMQX性能指标
check_emqx_performance() {
# 获取各种性能指标
local metrics
metrics=$(emqx_exec emqx_ctl metrics 2>/dev/null)
if [ -n "$metrics" ]; then
# 提取关键性能指标
local conn_pkt recv_pkt send_pkt
conn_pkt=$(echo "$metrics" | grep "packets.connect" | awk '{print $2}' || echo "0")
recv_pkt=$(echo "$metrics" | grep "packets.received" | awk '{print $2}' || echo "0")
send_pkt=$(echo "$metrics" | grep "packets.sent" | awk '{print $2}' || echo "0")
if [ -n "$conn_pkt" ]; then
output_result "EMQX_PACKETS_CONN" "$conn_pkt"
fi
if [ -n "$recv_pkt" ]; then
output_result "EMQX_PACKETS_RECV" "$recv_pkt"
fi
if [ -n "$send_pkt" ]; then
output_result "EMQX_PACKETS_SENT" "$send_pkt"
fi
fi
}
# 检测EMQX Dashboard状态
check_emqx_dashboard() {
local dashboard_status="未启用"
local dashboard_level="正常"
local dashboard_url=""
local dashboard_port="18083"
# 直接尝试访问Dashboard
local http_response
http_response=$(emqx_exec curl -s -e "curl -s -m 3 --max-time 3 http://localhost:$dashboard_port" 2>/dev/null | head -c 1000)
if [ -n "$http_response" ]; then
if echo "$http_response" | grep -qiE "emqx|dashboard|login|mqtt"; then
dashboard_status="可访问"
dashboard_level="正常"
dashboard_url="http://localhost:$dashboard_port"
local dashboard_version
dashboard_version=$(echo "$http_response" | grep -oE "v[0-9.]+" | head -1)
if [ -n "$dashboard_version" ]; then
output_result "EMQX_DASHBOARD_VERSION" "$dashboard_version"
fi
else
dashboard_status="响应异常"
dashboard_level="警告"
fi
fi
# 检查其他可能的Dashboard端口
if [ "$dashboard_status" = "未启用" ]; then
local alt_ports=("8081" "8083" "8883")
for alt_port in "${alt_ports[@]}"; do
local alt_response
alt_response=$(emqx_exec curl -s -m 2 --max-time 2 "http://localhost:$alt_port" 2>/dev/null | head -c 500)
if [ -n "$alt_response" ]; then
if echo "$alt_response" | grep -qiE "emqx|dashboard|login|mqtt"; then
dashboard_status="可访问(端口$alt_port)"
dashboard_level="正常"
dashboard_url="http://localhost:$alt_port"
break
fi
fi
done
fi
output_result "EMQX_DASHBOARD_STATUS" "$dashboard_status"
output_result "EMQX_DASHBOARD_LEVEL" "$dashboard_level"
if [ -n "$dashboard_url" ]; then
output_result "EMQX_DASHBOARD_URL" "$dashboard_url"
fi
}
# ==================== 主检测流程 ====================
main() {
log_info "开始EMQX深度检测..."
# 在检测前先找到实际的容器名
if command -v docker &> /dev/null; then
# 尝试精确匹配
local actual_container=$(docker ps --format "{{.Names}}" | grep -x "${EMQX_CONTAINER}" | head -1)
# 如果精确匹配失败,尝试模糊匹配
if [ -z "$actual_container" ]; then
actual_container=$(docker ps --format "{{.Names}}" | grep -i "emqx" | head -1)
fi
# 更新EMQX_CONTAINER为实际找到的容器名
if [ -n "$actual_container" ]; then
EMQX_CONTAINER="$actual_container"
fi
fi
if [ -z "$EMQX_CONTAINER" ]; then
log_warn "EMQX容器未运行"
output_result "EMQX_CONTAINER_STATUS" "未运行"
return 1
fi
output_result "EMQX_CONTAINER" "$EMQX_CONTAINER"
output_result "EMQX_CONTAINER_STATUS" "运行中"
# 执行各项深度检测(添加错误处理,确保部分失败不影响其他检测)
check_emqx_status_detail 2>/dev/null || true
check_emqx_clients_detail 2>/dev/null || true
check_emqx_subscriptions_detail 2>/dev/null || true
check_emqx_messages_stats 2>/dev/null || true
check_emqx_topics_detail 2>/dev/null || true
check_emqx_routes_detail 2>/dev/null || true
check_emqx_listeners_detail 2>/dev/null || true
check_emqx_cluster_detail 2>/dev/null || true
check_emqx_connection_limits 2>/dev/null || true
check_emqx_memory 2>/dev/null || true
check_emqx_sessions_detail 2>/dev/null || true
check_emqx_plugins 2>/dev/null || true
check_emqx_rules 2>/dev/null || true
check_emqx_alarms 2>/dev/null || true
check_emqx_performance 2>/dev/null || true
check_emqx_dashboard 2>/dev/null || true
log_info "EMQX深度检测完成"
}
# 执行主函数
main
#!/bin/bash
################################################################################
# Java应用检测模块
# 功能: 检测Java容器状态、版本、JVM内存、GC状态等
# 作者: Claude Code
# 日期: 2026-07-20
################################################################################
# 获取脚本所在目录并加载依赖
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
# Java容器名称
JAVA_CONTAINER="${CONTAINERS[java]}"
# ==================== 辅助函数 ====================
# 在Java容器中执行命令
java_exec() {
docker exec "$JAVA_CONTAINER" $@ 2>&1
}
# ==================== 检测函数 ====================
# 检测Java容器状态(使用模糊匹配)
check_java_container() {
local container_status="未运行"
local level="严重"
if command -v docker &> /dev/null; then
# 使用当前JAVA_CONTAINER变量值进行检测
if docker ps --format "{{.Names}}" | grep -q "^${JAVA_CONTAINER}$"; then
container_status="运行中"
level="正常"
elif docker ps --format "{{.Names}}" | grep -qi "${JAVA_CONTAINER}"; then
container_status="运行中"
level="正常"
else
# 检查容器是否存在但未运行
if docker ps -a --format "{{.Names}}" | grep -qi "${JAVA_CONTAINER}"; then
container_status="已停止"
level="警告"
fi
fi
fi
output_result "JAVA_CONTAINER_STATUS" "$container_status"
output_result "JAVA_CONTAINER_LEVEL" "$level"
if [ "$level" != "正常" ]; then
return 1
fi
return 0
}
# 检测Java版本
check_java_version() {
local version=""
version=$(java_exec java -version 2>&1 | grep -i "version" | head -1)
if [ -n "$version" ]; then
# 提取版本号 - 支持多种格式
version=$(echo "$version" | sed -n 's/.*version "\([^"]*\)".*/\1/ip' | head -1)
if [ -n "$version" ]; then
output_result "JAVA_VERSION" "$version"
fi
fi
}
# 检测Java进程
check_java_process() {
local java_pid=""
java_pid=$(java_exec jps 2>/dev/null | grep -v "Jps" | head -1 | awk '{print $1}')
if [ -n "$java_pid" ]; then
output_result "JAVA_PID" "$java_pid"
# 获取JVM内存信息
local proc_info
proc_info=$(java_exec cat /proc/$java_pid/status 2>/dev/null)
if [ -n "$proc_info" ]; then
local vm_size vm_rss threads
vm_size=$(echo "$proc_info" | grep "^VmSize:" | awk '{print int($2/1024/1024)}')
vm_rss=$(echo "$proc_info" | grep "^VmRSS:" | awk '{print int($2/1024/1024)}')
threads=$(echo "$proc_info" | grep "^Threads:" | awk '{print $2}')
[ -n "$vm_size" ] && output_result "JAVA_VM_SIZE" "${vm_size}MB"
[ -n "$vm_rss" ] && output_result "JAVA_VM_RSS" "${vm_rss}MB"
[ -n "$threads" ] && output_result "JAVA_THREADS" "$threads"
fi
fi
}
# 检测JVM堆内存
check_jvm_heap() {
local heap_info=""
# 先获取Java进程ID
local java_pid
java_pid=$(java_exec jps 2>/dev/null | grep -v "Jps" | head -1 | awk '{print $1}')
if [ -z "$java_pid" ]; then
return
fi
heap_info=$(java_exec jstat -gc "$java_pid" 2>/dev/null | tail -1)
if [ -n "$heap_info" ]; then
# 解析jstat输出
local ec eu oc ou
read ec eu oc ou < <(echo "$heap_info" | awk '{print $3, $4, $5, $6}')
if [ -n "$ec" ] && [ -n "$eu" ]; then
local heap_capacity=$((ec / 1024))
local heap_used=$((eu / 1024))
if [ "$heap_capacity" -gt 0 ]; then
local heap_percent=$((heap_used * 100 / heap_capacity))
output_result "JAVA_HEAP_CAPACITY" "${heap_capacity}MB"
output_result "JAVA_HEAP_USED" "${heap_used}MB"
output_result "JAVA_HEAP_PERCENT" "${heap_percent}%"
# 判断堆内存使用率
local level="正常"
if [ "$heap_percent" -ge 90 ]; then
level="严重"
elif [ "$heap_percent" -ge 80 ]; then
level="警告"
fi
output_result "JAVA_HEAP_LEVEL" "$level"
fi
fi
fi
}
# 检测GC状态
check_gc_status() {
local gc_logs=""
gc_logs=$(docker logs --tail 500 "$JAVA_CONTAINER" 2>&1 | grep -iE "GC|heap" | tail -20)
if [ -n "$gc_logs" ]; then
# 统计Full GC次数
local full_gc_count
full_gc_count=$(echo "$gc_logs" | grep -c "Full GC" || echo "0")
# 统计Young GC次数
local young_gc_count
young_gc_count=$(echo "$gc_logs" | grep -cE "GC \(|GC \(Allocation Failure" || echo "0")
output_result "JAVA_FULL_GC" "$full_gc_count"
output_result "JAVA_YOUNG_GC" "$young_gc_count"
# 判断GC状态
local level="正常"
if [ "$full_gc_count" -gt 5 ]; then
level="严重"
elif [ "$full_gc_count" -gt 2 ]; then
level="警告"
fi
output_result "JAVA_GC_LEVEL" "$level"
fi
}
# 检测Java线程数
check_java_threads() {
local thread_count=0
# 获取第一个Java进程的线程数
local java_pid
java_pid=$(java_exec jps 2>/dev/null | grep -v "Jps" | awk '{print $1}' | head -1)
if [ -n "$java_pid" ]; then
thread_count=$(docker exec "$JAVA_CONTAINER" cat /proc/$java_pid/status 2>/dev/null | grep "^Threads:" | awk '{print $2}')
if [ -n "$thread_count" ]; then
output_result "JAVA_THREAD_COUNT" "$thread_count"
# 判断线程数
local level="正常"
if [ "$thread_count" -ge 3000 ]; then
level="严重"
elif [ "$thread_count" -ge 1000 ]; then
level="警告"
fi
output_result "JAVA_THREAD_LEVEL" "$level"
fi
fi
}
# 检测Java应用日志
check_java_logs() {
local log_errors=0
log_errors=$(docker logs --tail 1000 "$JAVA_CONTAINER" 2>&1 | grep -ciE "ERROR|Exception" || echo "0")
log_errors=$(echo "$log_errors" | tail -1)
output_result "JAVA_LOG_ERRORS" "$log_errors"
if [ "$log_errors" -gt 50 ]; then
output_result "JAVA_LOG_LEVEL" "警告"
else
output_result "JAVA_LOG_LEVEL" "正常"
fi
}
# 检测Spring Boot Actuator端点
check_springboot_actuator() {
# 检测可用命令(curl或wget)
local http_cmd=""
if docker exec "$JAVA_CONTAINER" which curl >/dev/null 2>&1; then
http_cmd="curl -s -m 2 --max-time 2"
elif docker exec "$JAVA_CONTAINER" which wget >/dev/null 2>&1; then
http_cmd="wget -q -O - -T 2 --timeout=2"
else
output_result "SPRINGBOOT_ACTUATOR" "检测工具不可用"
return
fi
# 常见的Actuator端点路径和端口
local actuator_ports=("8080" "8999")
local actuator_paths=("/actuator/health" "/health" "/actuator" "/")
local actuator_found="false"
local health_status="未检测"
for port in "${actuator_ports[@]}"; do
for path in "${actuator_paths[@]}"; do
# 尝试访问端点(超时2秒)
local response
response=$(docker exec "$JAVA_CONTAINER" $http_cmd "http://localhost:${port}${path}" 2>/dev/null | head -c 500)
if [ -n "$response" ]; then
if echo "$response" | grep -qiE '"status"|"UP"|"DOWN"|"HEALTH"'; then
actuator_found="true"
# 解析健康状态
if echo "$response" | grep -qi '"status"[[:space:]]*:[[:space:]]*"UP"'; then
health_status="UP"
elif echo "$response" | grep -qi '"status"[[:space:]]*:[[:space:]]*"DOWN"'; then
health_status="DOWN"
else
health_status="UNKNOWN"
fi
break 2
elif echo "$response" | grep -qiE "403|401|禁止|拒绝|unauthorized"; then
actuator_found="true"
health_status="需要认证"
break 2
fi
fi
done
if [ "$actuator_found" = "true" ]; then
break
fi
done
if [ "$actuator_found" = "true" ]; then
output_result "SPRINGBOOT_ACTUATOR" "已启用"
output_result "SPRINGBOOT_HEALTH_STATUS" "$health_status"
# 判断健康状态等级
local level="正常"
if [ "$health_status" = "DOWN" ]; then
level="严重"
elif [ "$health_status" = "UNKNOWN" ]; then
level="警告"
fi
output_result "SPRINGBOOT_HEALTH_LEVEL" "$level"
else
output_result "SPRINGBOOT_ACTUATOR" "未启用或不可访问"
fi
}
# 检测Java容器资源使用
check_java_resources() {
# CPU使用率
local cpu_percent
cpu_percent=$(docker stats --no-stream --format '{{.CPUPerc}}' "$JAVA_CONTAINER" 2>/dev/null | tr -d '%')
if [ -n "$cpu_percent" ]; then
output_result "JAVA_CPU_USAGE" "$cpu_percent"
fi
# 内存使用
local mem_usage mem_percent
mem_usage=$(docker stats --no-stream --format '{{.MemUsage}}' "$JAVA_CONTAINER" 2>/dev/null)
if [ -n "$mem_usage" ]; then
output_result "JAVA_MEMORY_USAGE" "$mem_usage"
fi
mem_percent=$(docker stats --no-stream --format '{{.MemPerc}}' "$JAVA_CONTAINER" 2>/dev/null | tr -d '%')
if [ -n "$mem_percent" ]; then
output_result "JAVA_MEMORY_PERCENT" "$mem_percent"
fi
}
# 检测容器内进程列表
check_java_process_list() {
local process_list
process_list=$(java_exec ps aux 2>/dev/null | grep -v "PID" | grep -v "ps aux" | awk '{print $1, $2, $3, $4, $11}' | head -20)
if [ -n "$process_list" ]; then
# 统计进程数
local total_processes
total_processes=$(echo "$process_list" | wc -l)
output_result "JAVA_PROCESS_COUNT" "$total_processes"
# 格式化进程列表(USER PID CPU% MEM% COMMAND)
local formatted
formatted=$(echo "$process_list" | tr '\n' '|' | sed 's/|$//')
output_result "JAVA_PROCESS_LIST" "$formatted"
# 获取Java进程详情
local java_processes
java_processes=$(echo "$process_list" | grep -i "java" | head -10)
if [ -n "$java_processes" ]; then
output_result "JAVA_PROCESSES_DETAIL" "$(echo "$java_processes" | tr '\n' '|' | sed 's/|$//')"
fi
fi
}
# ==================== 主检测流程 ====================
main() {
log_info "开始Java应用检测..."
# 在检测前先找到实际的容器名
if command -v docker &> /dev/null; then
# 尝试精确匹配
local actual_container=$(docker ps --format "{{.Names}}" | grep -x "${JAVA_CONTAINER}" | head -1)
# 如果精确匹配失败,尝试模糊匹配
if [ -z "$actual_container" ]; then
actual_container=$(docker ps --format "{{.Names}}" | grep -iE "java|api" | head -1)
fi
# 更新JAVA_CONTAINER为实际找到的容器名
if [ -n "$actual_container" ]; then
JAVA_CONTAINER="$actual_container"
fi
fi
# 输出实际使用的容器名
output_result "JAVA_CONTAINER" "$JAVA_CONTAINER"
# 检查容器状态
if ! check_java_container; then
log_warn "Java容器未运行,跳过其他检测"
return
fi
# 执行各项检测
check_java_version
check_java_process
check_jvm_heap
check_gc_status
check_java_threads
check_java_logs
check_springboot_actuator
check_java_resources
check_java_process_list
log_info "Java应用检测完成"
}
# 执行主函数
main
\ No newline at end of file
#!/bin/bash
################################################################################
# Python应用检测模块
# 功能: 检测Python容器状态、进程、资源使用等
# 作者: Claude Code
# 日期: 2026-07-20
################################################################################
# 获取脚本所在目录并加载依赖
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
# Python容器名称
PYTHON_CONTAINER="${CONTAINERS[python]}"
# ==================== 辅助函数 ====================
python_exec() {
docker exec "$PYTHON_CONTAINER" $@ 2>/dev/null
}
# ==================== 检测函数 ====================
# 检测Python容器状态
check_python_container() {
local matched_container=""
if command -v docker &> /dev/null; then
# 尝试精确匹配
matched_container=$(docker ps --format "{{.Names}}" | grep -x "${PYTHON_CONTAINER}" | head -1)
# 如果精确匹配失败,尝试模糊匹配
if [ -z "$matched_container" ] && [ -n "$PYTHON_CONTAINER" ]; then
matched_container=$(docker ps --format "{{.Names}}" | grep -i "${PYTHON_CONTAINER}" | head -1)
fi
fi
if [ -n "$matched_container" ]; then
eval "PYTHON_CONTAINER='${matched_container}'"
output_result "PYTHON_CONTAINER_STATUS" "运行中 (${PYTHON_CONTAINER})"
output_result "PYTHON_CONTAINER_LEVEL" "正常"
return 0
else
# 检查容器是否存在但未运行
matched_container=$(docker ps -a --format "{{.Names}}" | grep -i "${PYTHON_CONTAINER}" | head -1)
if [ -n "$matched_container" ]; then
output_result "PYTHON_CONTAINER_STATUS" "已停止 (${matched_container})"
output_result "PYTHON_CONTAINER_LEVEL" "警告"
else
output_result "PYTHON_CONTAINER_STATUS" "未运行"
output_result "PYTHON_CONTAINER_LEVEL" "严重"
fi
return 1
fi
}
# 检测Python版本
check_python_version() {
local py_version
py_version=$(python_exec python --version 2>&1 | awk '{print $2}')
[ -n "$py_version" ] && output_result "PYTHON_VERSION" "$py_version"
}
# 检测Python进程数
check_python_processes() {
local py_count
py_count=$(python_exec ps aux 2>/dev/null | grep -c "python" || echo "0")
output_result "PYTHON_PROCESSES" "$py_count"
}
# 检测容器内进程列表
check_python_process_list() {
local process_list
process_list=$(python_exec ps aux 2>/dev/null | grep -v "PID" | grep -v "ps aux" | awk '{print $1, $2, $3, $4, $11}' | head -20)
if [ -n "$process_list" ]; then
# 统计进程数
local total_processes
total_processes=$(echo "$process_list" | wc -l)
output_result "PYTHON_PROCESS_COUNT" "$total_processes"
# 格式化进程列表(USER PID CPU% MEM% COMMAND)
local formatted
formatted=$(echo "$process_list" | tr '\n' '|' | sed 's/|$//')
output_result "PYTHON_PROCESS_LIST" "$formatted"
# 获取Python进程详情
local py_processes
py_processes=$(echo "$process_list" | grep -i "python" | head -10)
if [ -n "$py_processes" ]; then
output_result "PYTHON_PROCESSES_DETAIL" "$(echo "$py_processes" | tr '\n' '|' | sed 's/|$//')"
fi
fi
}
# 检测Python容器资源使用
check_python_resources() {
# 内存使用
local py_mem
py_mem=$(docker stats --no-stream --format "{{.MemUsage}}" "$PYTHON_CONTAINER" 2>/dev/null | head -1)
[ -n "$py_mem" ] && output_result "PYTHON_MEMORY" "$py_mem"
# CPU使用率
local py_cpu
py_cpu=$(docker stats --no-stream --format "{{.CPUPerc}}" "$PYTHON_CONTAINER" 2>/dev/null | head -1)
[ -n "$py_cpu" ] && output_result "PYTHON_CPU" "$py_cpu"
}
# 检测Python应用日志
check_python_logs() {
local log_errors=0
log_errors=$(docker logs --tail 500 "$PYTHON_CONTAINER" 2>&1 | grep -ciE "ERROR|Exception|Traceback" || echo "0")
log_errors=$(echo "$log_errors" | tail -1)
output_result "PYTHON_LOG_ERRORS" "$log_errors"
if [ "$log_errors" -gt 20 ]; then
output_result "PYTHON_LOG_LEVEL" "警告"
else
output_result "PYTHON_LOG_LEVEL" "正常"
fi
}
# ==================== 主检测流程 ====================
main() {
log_info "开始Python应用检测..."
if ! check_python_container; then
log_warn "Python容器未运行,跳过其他检测"
return
fi
check_python_version
check_python_processes
check_python_resources
check_python_logs
check_python_process_list
log_info "Python应用检测完成"
}
main
#!/bin/bash
################################################################################
# Nginx基础检测模块
# 功能: 检测Nginx容器状态、配置、连接数等
# 作者: Claude Code
# 日期: 2026-07-20
################################################################################
# 获取脚本所在目录并加载依赖
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
# Nginx容器名称
NGINX_CONTAINER="${CONTAINERS[nginx]}"
# ==================== 辅助函数 ====================
nginx_exec() {
docker exec "$NGINX_CONTAINER" $@ 2>/dev/null
}
# ==================== 检测函数 ====================
# 检测Nginx容器状态
check_nginx_container() {
local matched_container=""
if command -v docker &> /dev/null; then
matched_container=$(docker ps --format "{{.Names}}" | grep -x "${NGINX_CONTAINER}" | head -1)
if [ -z "$matched_container" ] && [ -n "$NGINX_CONTAINER" ]; then
matched_container=$(docker ps --format "{{.Names}}" | grep -i "${NGINX_CONTAINER}" | head -1)
fi
fi
if [ -n "$matched_container" ]; then
eval "NGINX_CONTAINER='${matched_container}'"
output_result "NGINX_CONTAINER_STATUS" "运行中 (${NGINX_CONTAINER})"
output_result "NGINX_CONTAINER_LEVEL" "正常"
return 0
else
matched_container=$(docker ps -a --format "{{.Names}}" | grep -i "${NGINX_CONTAINER}" | head -1)
if [ -n "$matched_container" ]; then
output_result "NGINX_CONTAINER_STATUS" "已停止 (${matched_container})"
output_result "NGINX_CONTAINER_LEVEL" "警告"
else
output_result "NGINX_CONTAINER_STATUS" "未运行"
output_result "NGINX_CONTAINER_LEVEL" "严重"
fi
return 1
fi
}
# 检测Nginx版本
check_nginx_version() {
local nginx_version
nginx_version=$(nginx_exec sh -c "nginx -v 2>&1" | grep "nginx version" | sed 's/.*nginx\///')
[ -n "$nginx_version" ] && output_result "NGINX_VERSION" "$nginx_version"
}
# 检测Nginx配置
check_nginx_config() {
local nginx_conf
nginx_conf=$(nginx_exec nginx -t 2>&1 | grep "successful")
if [ -n "$nginx_conf" ]; then
output_result "NGINX_CONFIG" "正常"
else
output_result "NGINX_CONFIG" "异常"
fi
}
# 检测Nginx状态页
check_nginx_status() {
local nginx_status
nginx_status=$(nginx_exec curl -s localhost/nginx_status 2>/dev/null | head -1)
[ -n "$nginx_status" ] && output_result "NGINX_STATUS" "$nginx_status"
}
# 检测Nginx容器资源
check_nginx_resources() {
local mem_usage
mem_usage=$(docker stats --no-stream --format "{{.MemUsage}}" "$NGINX_CONTAINER" 2>/dev/null)
[ -n "$mem_usage" ] && output_result "NGINX_MEMORY" "$mem_usage"
}
# ==================== 主检测流程 ====================
main() {
log_info "开始Nginx基础检测..."
if ! check_nginx_container; then
log_warn "Nginx容器未运行,跳过其他检测"
return
fi
check_nginx_version
check_nginx_config
check_nginx_status
check_nginx_resources
log_info "Nginx基础检测完成"
}
main
#!/bin/bash
################################################################################
# Nacos基础检测模块
# 功能: 检测Nacos容器状态、服务实例数等
# 作者: Claude Code
# 日期: 2026-07-20
################################################################################
# 获取脚本所在目录并加载依赖
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
# Nacos容器名称
NACOS_CONTAINER="${CONTAINERS[nacos]}"
# ==================== 辅助函数 ====================
nacos_exec() {
docker exec "$NACOS_CONTAINER" $@ 2>/dev/null
}
nacos_api() {
local endpoint=$1
nacos_exec curl -s "http://localhost:8848/nacos/$endpoint" 2>/dev/null
}
# ==================== 检测函数 ====================
# 检测Nacos容器状态
check_nacos_container() {
local matched_container=""
if command -v docker &> /dev/null; then
matched_container=$(docker ps --format "{{.Names}}" | grep -x "${NACOS_CONTAINER}" | head -1)
if [ -z "$matched_container" ] && [ -n "$NACOS_CONTAINER" ]; then
matched_container=$(docker ps --format "{{.Names}}" | grep -i "${NACOS_CONTAINER}" | head -1)
fi
fi
if [ -n "$matched_container" ]; then
eval "NACOS_CONTAINER='${matched_container}'"
output_result "NACOS_CONTAINER_STATUS" "运行中 (${NACOS_CONTAINER})"
output_result "NACOS_CONTAINER_LEVEL" "正常"
return 0
else
matched_container=$(docker ps -a --format "{{.Names}}" | grep -i "${NACOS_CONTAINER}" | head -1)
if [ -n "$matched_container" ]; then
output_result "NACOS_CONTAINER_STATUS" "已停止 (${matched_container})"
output_result "NACOS_CONTAINER_LEVEL" "警告"
else
output_result "NACOS_CONTAINER_STATUS" "未运行"
output_result "NACOS_CONTAINER_LEVEL" "严重"
fi
return 1
fi
}
# 检测Nacos健康状态
check_nacos_health() {
local nacos_health
nacos_health=$(nacos_api "v1/console/health/readiness" 2>/dev/null)
[ -n "$nacos_health" ] && output_result "NACOS_HEALTH" "$nacos_health"
}
# 检测Nacos容器资源
check_nacos_resources() {
local nacos_mem
nacos_mem=$(docker stats --no-stream --format "{{.MemUsage}}" "$NACOS_CONTAINER" 2>/dev/null)
[ -n "$nacos_mem" ] && output_result "NACOS_MEMORY" "$nacos_mem"
}
# 检测Nacos服务数量
check_nacos_services() {
local services
services=$(nacos_api "v1/ns/service/list?pageNo=1&pageSize=100&namespaceId=" 2>/dev/null)
if [ -n "$services" ]; then
local service_count
service_count=$(echo "$services" | grep -o '"count":[0-9]*' | cut -d: -f2 | head -1)
[ -n "$service_count" ] && output_result "NACOS_SERVICES_COUNT" "$service_count"
fi
}
# ==================== 主检测流程 ====================
main() {
log_info "开始Nacos基础检测..."
if ! check_nacos_container; then
log_warn "Nacos容器未运行,跳过其他检测"
return
fi
check_nacos_health
check_nacos_resources
check_nacos_services
log_info "Nacos基础检测完成"
}
main
#!/bin/bash
################################################################################
# 应用日志分析模块
# 功能: 检测Java、Python应用日志中的错误和异常
# 作者: Claude Code
# 日期: 2026-07-20
################################################################################
# 获取脚本所在目录并加载依赖
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_app_log_errors() {
local log_dirs=("/data/services/api/*/log" "/data/services/api/python*/log")
local total_errors=0
for log_dir in $log_dirs; do
if [ -d "$log_dir" ]; then
local error_count
error_count=$(find "$log_dir" -name "*.log" -mtime -1 -exec grep -lE "ERROR|Exception" {} \; 2>/dev/null | wc -l)
total_errors=$((total_errors + error_count))
fi
done
output_result "APP_LOG_ERRORS_24H" "$total_errors"
if [ "$total_errors" -gt 100 ]; then
output_result "APP_LOG_LEVEL" "严重"
elif [ "$total_errors" -gt 10 ]; then
output_result "APP_LOG_LEVEL" "警告"
else
output_result "APP_LOG_LEVEL" "正常"
fi
}
# 检测Docker容器日志错误
check_container_log_errors() {
if ! command -v docker &> /dev/null; then
return
fi
local total_container_errors=0
local running_containers
running_containers=$(docker ps --format "{{.Names}}" 2>/dev/null | head -20)
for container in $running_containers; do
local error_count
error_count=$(docker logs --tail 200 "$container" 2>&1 | grep -ciE "ERROR|Exception|FATAL" || echo "0")
error_count=$(echo "$error_count" | tail -1)
if [ -n "$error_count" ] && [ "$error_count" -gt 0 ]; then
output_result "CONTAINER_LOG_ERRORS_${container}" "$error_count"
total_container_errors=$((total_container_errors + error_count))
fi
done
output_result "CONTAINER_LOG_ERRORS_TOTAL" "$total_container_errors"
if [ "$total_container_errors" -gt 200 ]; then
output_result "CONTAINER_LOG_LEVEL" "严重"
elif [ "$total_container_errors" -gt 50 ]; then
output_result "CONTAINER_LOG_LEVEL" "警告"
else
output_result "CONTAINER_LOG_LEVEL" "正常"
fi
}
# 检测系统日志错误
check_system_log_errors() {
local sys_errors=0
# 检查 /var/log/messages 或 /var/log/syslog
if [ -f "/var/log/messages" ]; then
sys_errors=$(grep -cE "error|ERROR|critical|CRITICAL" /var/log/messages 2>/dev/null || echo "0")
elif [ -f "/var/log/syslog" ]; then
sys_errors=$(grep -cE "error|ERROR|critical|CRITICAL" /var/log/syslog 2>/dev/null || echo "0")
fi
if [ "$sys_errors" -gt 0 ]; then
output_result "SYSLOG_ERRORS" "$sys_errors"
fi
}
# ==================== 主检测流程 ====================
main() {
log_info "开始应用日志分析..."
check_app_log_errors
check_container_log_errors
check_system_log_errors
log_info "应用日志分析完成"
}
main
#!/bin/bash
################################################################################
# Nginx深度检测模块
# 功能: 深度检测Nginx连接数、请求统计、性能指标、配置详情等
# 作者: Claude Code
# 日期: 2026-07-20
################################################################################
# 获取脚本所在目录并加载依赖
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
# Nginx容器名称
NGINX_CONTAINER="${CONTAINERS[nginx]}"
# ==================== 辅助函数 ====================
# 在Nginx容器中执行命令
nginx_exec() {
docker exec "$NGINX_CONTAINER" $@ 2>/dev/null
}
# ==================== 深度检测函数 ====================
# 检测Nginx版本详情
check_nginx_version_detail() {
local nginx_version
# 方法1: 直接在容器内执行nginx -v
nginx_version=$(nginx_exec sh -c "nginx -v 2>&1" | grep "nginx version" | sed 's/.*nginx\///' | sed 's/ $//')
# 方法2: 如果方法1失败,尝试使用which找到nginx路径
if [ -z "$nginx_version" ]; then
local nginx_path
nginx_path=$(nginx_exec which nginx 2>/dev/null)
if [ -n "$nginx_path" ]; then
nginx_version=$(nginx_exec "$nginx_path" -v 2>&1 | grep "nginx version" | sed 's/.*nginx\///' | sed 's/ $//')
fi
fi
# 方法3: 如果仍然失败,从容器标签获取
if [ -z "$nginx_version" ]; then
local image_version
image_version=$(docker inspect --format='{{.Config.Image}}' "$NGINX_CONTAINER" 2>/dev/null | grep -oE ':[0-9.]+' | sed 's/://')
if [ -n "$image_version" ]; then
nginx_version="$image_version"
fi
fi
if [ -n "$nginx_version" ]; then
output_result "NGINX_VERSION" "$nginx_version"
fi
}
# 检测Nginx连接统计
check_nginx_connections() {
# 从状态页面获取连接信息
local status_data
status_data=$(nginx_exec curl -s localhost/nginx_status 2>/dev/null)
if [ -n "$status_data" ]; then
# 解析active connections
local active_conn
active_conn=$(echo "$status_data" | grep "Active connections" | awk '{print $3}' || echo "0")
output_result "NGINX_ACTIVE_CONNECTIONS" "$active_conn"
# 解析accepted connections
local accepted_conn
accepted_conn=$(echo "$status_data" | awk 'NR==3 {print $1}' || echo "0")
output_result "NGINX_ACCEPTED_CONNECTIONS" "$accepted_conn"
# 解析handled connections
local handled_conn
handled_conn=$(echo "$status_data" | awk 'NR==3 {print $2}' || echo "0")
output_result "NGINX_HANDLED_CONNECTIONS" "$handled_conn"
# 解析请求数
local requests
requests=$(echo "$status_data" | awk 'NR==3 {print $3}' || echo "0")
output_result "NGINX_REQUESTS_TOTAL" "$requests"
fi
}
# 检测Nginx进程状态
check_nginx_process() {
local nginx_pid
nginx_pid=$(nginx_exec cat /var/run/nginx.pid 2>/dev/null)
if [ -n "$nginx_pid" ]; then
output_result "NGINX_PID" "$nginx_pid"
# 获取进程数(master + worker)- 使用多种方法
local process_count
# 方法1: 使用pgrep查找nginx进程
process_count=$(nginx_exec pgrep -f nginx 2>/dev/null | wc -l)
# 方法2: 如果pgrep失败,使用ps aux
if [ "$process_count" -eq 0 ]; then
process_count=$(nginx_exec ps aux 2>/dev/null | grep -v grep | grep -c "[n]ginx" || echo "0")
fi
if [ "$process_count" -gt 0 ]; then
output_result "NGINX_PROCESSES" "$process_count"
fi
fi
}
# 检测Nginx监听端口
check_nginx_listening() {
local listening_ports
listening_ports=$(nginx_exec ss -tlnp 2>/dev/null | grep nginx | awk '{print $4}' | grep -oE '[0-9]+$' | sort -u | tr '\n' ',' | sed 's/,$//')
if [ -z "$listening_ports" ]; then
listening_ports=$(nginx_exec netstat -tlnp 2>/dev/null | grep nginx | awk '{print $4}' | grep -oE '[0-9]+$' | sort -u | tr '\n' ',' | sed 's/,$//')
fi
if [ -n "$listening_ports" ]; then
output_result "NGINX_LISTENING_PORTS" "$listening_ports"
fi
}
# 检测Nginx配置详情
check_nginx_config_detail() {
# 测试配置文件
local config_test
config_test=$(nginx_exec nginx -t 2>&1)
if echo "$config_test" | grep -q "successful"; then
output_result "NGINX_CONFIG_STATUS" "正常"
output_result "NGINX_CONFIG_LEVEL" "正常"
else
output_result "NGINX_CONFIG_STATUS" "异常"
output_result "NGINX_CONFIG_LEVEL" "严重"
# 获取错误信息
local error_msg
error_msg=$(echo "$config_test" | grep "error" | head -1)
[ -n "$error_msg" ] && output_result "NGINX_CONFIG_ERROR" "$error_msg"
fi
}
# 检测Nginx worker进程配置
check_nginx_worker_config() {
# 获取worker进程数
local worker_processes
worker_processes=$(nginx_exec sh -c "nginx -T 2>/dev/null | grep 'worker_processes' | grep -v '#' | awk '{print \$2}' | head -1")
if [ -n "$worker_processes" ]; then
output_result "NGINX_WORKER_PROCESSES" "$worker_processes"
fi
# 获取worker连接数
local worker_connections
worker_connections=$(nginx_exec sh -c "nginx -T 2>/dev/null | grep 'worker_connections' | grep -v '#' | awk '{print \$2}' | head -1")
if [ -n "$worker_connections" ]; then
output_result "NGINX_WORKER_CONNECTIONS" "$worker_connections"
fi
}
# 检测Nginx日志文件
check_nginx_logs() {
# 检查access log大小
local access_log_size
access_log_size=$(nginx_exec ls -lh /var/log/nginx/access.log 2>/dev/null | awk '{print $5}')
if [ -n "$access_log_size" ]; then
output_result "NGINX_ACCESS_LOG_SIZE" "$access_log_size"
fi
# 检查error log大小
local error_log_size
error_log_size=$(nginx_exec ls -lh /var/log/nginx/error.log 2>/dev/null | awk '{print $5}')
if [ -n "$error_log_size" ]; then
output_result "NGINX_ERROR_LOG_SIZE" "$error_log_size"
fi
# 统计最近的错误数量(最近100行)
local recent_errors
recent_errors=$(nginx_exec tail -100 /var/log/nginx/error.log 2>/dev/null | grep -c "error" || echo "0")
output_result "NGINX_RECENT_ERRORS" "$recent_errors"
}
# 检测Nginx SSL证书状态
check_nginx_ssl() {
# 检查是否启用了SSL
local ssl_enabled
ssl_enabled=$(nginx_exec sh -c "nginx -T 2>/dev/null | grep -c 'listen.*ssl'" || echo "0")
if [ "$ssl_enabled" -gt 0 ]; then
output_result "NGINX_SSL_ENABLED" "是"
# 获取SSL证书过期时间(如果有443端口)
local cert_expiry
cert_expiry=$(nginx_exec openssl x509 -in /etc/nginx/ssl/nginx.crt -noout -enddate 2>/dev/null | cut -d= -f2)
if [ -n "$cert_expiry" ]; then
output_result "NGINX_SSL_CERT_EXPIRY" "$cert_expiry"
fi
else
output_result "NGINX_SSL_ENABLED" "否"
fi
}
# 检测Nginx缓存状态
check_nginx_cache() {
# 检查是否配置了缓存
local cache_enabled
cache_enabled=$(nginx_exec sh -c "nginx -T 2>/dev/null | grep -c 'proxy_cache_path'" || echo "0")
if [ "$cache_enabled" -gt 0 ]; then
output_result "NGINX_CACHE_ENABLED" "是"
# 获取缓存路径
local cache_path
cache_path=$(nginx_exec sh -c "nginx -T 2>/dev/null | grep 'proxy_cache_path' | grep -v '#' | awk '{print \$2}' | head -1")
if [ -n "$cache_path" ]; then
output_result "NGINX_CACHE_PATH" "$cache_path"
fi
else
output_result "NGINX_CACHE_ENABLED" "否"
fi
}
# 检测Nginx upstream状态
check_nginx_upstream() {
# 检查upstream配置
local upstream_count
upstream_count=$(nginx_exec sh -c "nginx -T 2>/dev/null | grep -c 'upstream'" || echo "0")
if [ "$upstream_count" -gt 0 ]; then
output_result "NGINX_UPSTREAM_COUNT" "$upstream_count"
# 获取upstream名称列表
local upstreams
upstreams=$(nginx_exec sh -c "nginx -T 2>/dev/null | grep 'upstream' | grep -v '#' | awk '{print \$2}' | tr '\n' ',' | sed 's/,$//'")
[ -n "$upstreams" ] && output_result "NGINX_UPSTREAMS" "$upstreams"
else
output_result "NGINX_UPSTREAM_COUNT" "0"
fi
}
# 检测Nginx server块配置
check_nginx_server_blocks() {
# 统计server块数量
local server_count
server_count=$(nginx_exec sh -c "nginx -T 2>/dev/null | grep -c 'server_name'" || echo "0")
if [ -n "$server_count" ]; then
output_result "NGINX_SERVER_BLOCKS" "$server_count"
fi
}
# 检测Nginx访问日志状态码分布
check_nginx_access_log_stats() {
local access_log="/var/log/nginx/access.log"
# 检查日志文件是否存在
if ! nginx_exec test -f "$access_log" 2>/dev/null; then
return
fi
# 统计最近1000行日志的状态码分布
local status_2xx status_3xx status_4xx status_5xx
status_2xx=$(nginx_exec tail -1000 "$access_log" 2>/dev/null | awk '$9 ~ /^2/ {count++} END {print count+0}')
status_3xx=$(nginx_exec tail -1000 "$access_log" 2>/dev/null | awk '$9 ~ /^3/ {count++} END {print count+0}')
status_4xx=$(nginx_exec tail -1000 "$access_log" 2>/dev/null | awk '$9 ~ /^4/ {count++} END {print count+0}')
status_5xx=$(nginx_exec tail -1000 "$access_log" 2>/dev/null | awk '$9 ~ /^5/ {count++} END {print count+0}')
output_result "NGINX_STATUS_2XX" "${status_2xx:-0}"
output_result "NGINX_STATUS_3XX" "${status_3xx:-0}"
output_result "NGINX_STATUS_4XX" "${status_4xx:-0}"
output_result "NGINX_STATUS_5XX" "${status_5xx:-0}"
# 计算错误率
local total_requests=$((status_2xx + status_3xx + status_4xx + status_5xx))
if [ "$total_requests" -gt 0 ]; then
local error_rate=$(( (status_4xx + status_5xx) * 100 / total_requests ))
output_result "NGINX_ERROR_RATE" "${error_rate}%"
fi
}
# 检测Nginx运行时间
check_nginx_uptime() {
local nginx_pid
nginx_pid=$(nginx_exec cat /var/run/nginx.pid 2>/dev/null)
if [ -n "$nginx_pid" ]; then
# 获取进程运行时间
local uptime_seconds
uptime_seconds=$(nginx_exec ps -p "$nginx_pid" -o etimes= 2>/dev/null | tr -d ' ')
if [ -n "$uptime_seconds" ] && [ "$uptime_seconds" -gt 0 ]; then
local uptime_days=$((uptime_seconds / 86400))
output_result "NGINX_UPTIME_DAYS" "$uptime_days"
fi
fi
}
# 检测Nginx容器资源使用
check_nginx_resources() {
# CPU使用率
local cpu_percent
cpu_percent=$(docker stats --no-stream --format '{{.CPUPerc}}' "$NGINX_CONTAINER" 2>/dev/null | tr -d '%')
if [ -n "$cpu_percent" ]; then
output_result "NGINX_CPU_USAGE" "$cpu_percent"
fi
# 内存使用
local mem_usage mem_percent
mem_usage=$(docker stats --no-stream --format '{{.MemUsage}}' "$NGINX_CONTAINER" 2>/dev/null)
if [ -n "$mem_usage" ]; then
output_result "NGINX_MEMORY_USAGE" "$mem_usage"
fi
mem_percent=$(docker stats --no-stream --format '{{.MemPerc}}' "$NGINX_CONTAINER" 2>/dev/null | tr -d '%')
if [ -n "$mem_percent" ]; then
output_result "NGINX_MEMORY_PERCENT" "$mem_percent"
fi
}
# ==================== 主检测流程 ====================
main() {
log_info "开始Nginx深度检测..."
# 检查容器状态(使用模糊匹配)
local matched_container=""
matched_container=$(docker ps --format "{{.Names}}" | grep -x "${NGINX_CONTAINER}" | head -1)
if [ -z "$matched_container" ] && [ -n "$NGINX_CONTAINER" ]; then
matched_container=$(docker ps --format "{{.Names}}" | grep -i "${NGINX_CONTAINER}" | head -1)
fi
if [ -z "$matched_container" ]; then
log_warn "Nginx容器未运行"
output_result "NGINX_CONTAINER_STATUS" "未运行"
return 1
fi
# 更新为实际容器名
eval "NGINX_CONTAINER='${matched_container}'"
output_result "NGINX_CONTAINER_STATUS" "运行中 (${NGINX_CONTAINER})"
# 执行各项深度检测
check_nginx_version_detail 2>/dev/null || true
check_nginx_connections 2>/dev/null || true
check_nginx_process 2>/dev/null || true
check_nginx_listening 2>/dev/null || true
check_nginx_config_detail 2>/dev/null || true
check_nginx_worker_config 2>/dev/null || true
check_nginx_logs 2>/dev/null || true
check_nginx_ssl 2>/dev/null || true
check_nginx_cache 2>/dev/null || true
check_nginx_upstream 2>/dev/null || true
check_nginx_server_blocks 2>/dev/null || true
check_nginx_access_log_stats 2>/dev/null || true
check_nginx_uptime 2>/dev/null || true
check_nginx_resources 2>/dev/null || true
log_info "Nginx深度检测完成"
}
# 执行主函数
main
\ No newline at end of file
#!/bin/bash
################################################################################
# Nacos深度检测模块
# 功能: 深度检测Nacos服务实例、配置数量、健康状态、Raft集群等
# 作者: Claude Code
# 日期: 2026-07-20
################################################################################
# 获取脚本所在目录并加载依赖
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
exit 1
fi
# Nacos容器名称
NACOS_CONTAINER="${CONTAINERS[nacos]}"
# ==================== 辅助函数 ====================
nacos_exec() {
docker exec "$NACOS_CONTAINER" $@ 2>/dev/null
}
nacos_api() {
local endpoint=$1
nacos_exec curl -s "http://localhost:8848/nacos/$endpoint" 2>/dev/null
}
# ==================== 深度检测函数 ====================
# 检测Nacos版本
check_nacos_version() {
local nacos_version
nacos_version=$(nacos_exec cat /home/nacos/version.txt 2>/dev/null | head -1)
if [ -n "$nacos_version" ]; then
output_result "NACOS_VERSION" "$nacos_version"
else
# 尝试从启动日志获取版本
nacos_version=$(nacos_exec cat /home/nacos/logs/start.out 2>/dev/null | grep "Nacos" | head -1)
[ -n "$nacos_version" ] && output_result "NACOS_VERSION" "$nacos_version"
fi
}
# 检测Nacos服务实例统计
check_nacos_services() {
# 获取命名空间列表
local namespaces
namespaces=$(nacos_api "v1/console/namespaces" 2>/dev/null)
if [ -n "$namespaces" ]; then
local namespace_count
namespace_count=$(echo "$namespaces" | grep -o "namespaceId" | wc -l)
output_result "NACOS_NAMESPACES" "$namespace_count"
fi
# 获取服务列表(默认命名空间)
local services
services=$(nacos_api "v1/ns/service/list?pageNo=1&pageSize=100&namespaceId=" 2>/dev/null)
if [ -n "$services" ]; then
local service_count
service_count=$(echo "$services" | grep -o '"count":[0-9]*' | cut -d: -f2 | head -1)
[ -n "$service_count" ] && output_result "NACOS_SERVICES_COUNT" "$service_count"
fi
}
# 检测Nacos实例统计
check_nacos_instances() {
local instances
instances=$(nacos_api "v1/ns/instance/list?pageNo=1&pageSize=100&namespaceId=" 2>/dev/null)
if [ -n "$instances" ]; then
local instance_count
instance_count=$(echo "$instances" | grep -o '"count":[0-9]*' | cut -d: -f2 | head -1)
[ -n "$instance_count" ] && output_result "NACOS_INSTANCES_COUNT" "$instance_count"
local healthy_count
healthy_count=$(echo "$instances" | grep -o '"healthyInstanceCount":[0-9]*' | cut -d: -f2 | head -1)
[ -n "$healthy_count" ] && output_result "NACOS_HEALTHY_INSTANCES" "$healthy_count"
# 计算健康率
if [ -n "$instance_count" ] && [ -n "$healthy_count" ] && [ "$instance_count" -gt 0 ]; then
local health_rate=$((healthy_count * 100 / instance_count))
output_result "NACOS_HEALTH_RATE" "${health_rate}%"
fi
fi
}
# 检测Nacos配置统计
check_nacos_configs() {
local configs
configs=$(nacos_api "v1/cs/configs?dataId=&group=&pageNo=1&pageSize=10&tenant=" 2>/dev/null)
if [ -n "$configs" ]; then
local config_count
config_count=$(echo "$configs" | grep -o '"total":[0-9]*' | cut -d: -f2 | head -1)
[ -n "$config_count" ] && output_result "NACOS_CONFIGS_COUNT" "$config_count"
fi
}
# 检测Nacos Raft集群状态
check_nacos_raft() {
local raft_info
raft_info=$(nacos_api "v1/ns/raft/state" 2>/dev/null)
if [ -n "$raft_info" ]; then
if echo "$raft_info" | grep -q "leader"; then
output_result "NACOS_RAFT_MODE" "是"
local role
role=$(echo "$raft_info" | grep -o '"role":"[^"]*"' | cut -d'"' -f4 | head -1)
[ -n "$role" ] && output_result "NACOS_RAFT_ROLE" "$role"
local node_count
node_count=$(echo "$raft_info" | grep -c "peer" || echo "0")
[ "$node_count" -gt 0 ] && output_result "NACOS_RAFT_NODES" "$node_count"
else
output_result "NACOS_RAFT_MODE" "否(单机模式)"
fi
fi
}
# 检测Nacos健康状态详情
check_nacos_health_detail() {
local health_status
health_status=$(nacos_api "v1/console/health/readiness" 2>/dev/null)
if [ -z "$health_status" ]; then
health_status=$(nacos_api "actuator/health" 2>/dev/null)
fi
if [ -z "$health_status" ]; then
health_status=$(nacos_exec curl -s -o /dev/null -w "%{http_code}" "http://localhost:8848/nacos/" 2>/dev/null)
if [ "$health_status" = "200" ] || [ "$health_status" = "302" ]; then
health_status="UP"
fi
fi
if [ -n "$health_status" ]; then
if echo "$health_status" | grep -qi "UP\|200\|302\|healthy"; then
output_result "NACOS_HEALTH_STATUS" "UP"
output_result "NACOS_HEALTH_LEVEL" "正常"
else
output_result "NACOS_HEALTH_STATUS" "DOWN"
output_result "NACOS_HEALTH_LEVEL" "严重"
fi
else
output_result "NACOS_HEALTH_STATUS" "DOWN"
output_result "NACOS_HEALTH_LEVEL" "严重"
fi
}
# 检测Nacos内存使用详情
check_nacos_memory_detail() {
local jvm_pid
jvm_pid=$(nacos_exec jps -l 2>/dev/null | grep nacos | awk '{print $1}')
if [ -n "$jvm_pid" ]; then
local heap_info
heap_info=$(nacos_exec jstat -gc "$jvm_pid" 2>/dev/null | tail -1)
if [ -n "$heap_info" ]; then
local heap_used heap_capacity
heap_used=$(echo "$heap_info" | awk '{print $4}' | tr -d ' ')
heap_capacity=$(echo "$heap_info" | awk '{print $6}' | tr -d ' ')
if [ -n "$heap_used" ] && [ -n "$heap_capacity" ] && [ "$heap_capacity" -gt 0 ]; then
local heap_usage=$((heap_used * 100 / heap_capacity))
output_result "NACOS_HEAP_USAGE" "${heap_usage}%"
fi
fi
fi
}
# 检测Nacos日志
check_nacos_logs() {
local log_size
log_size=$(nacos_exec du -sh /home/nacos/logs 2>/dev/null | awk '{print $1}')
if [ -n "$log_size" ]; then
output_result "NACOS_LOG_SIZE" "$log_size"
fi
local error_count
error_count=$(nacos_exec tail -100 /home/nacos/logs/nacos.log 2>/dev/null | grep -c "ERROR" || echo "0")
output_result "NACOS_RECENT_ERRORS" "$error_count"
}
# 检测Nacos容器资源
check_nacos_resources() {
local cpu_percent
cpu_percent=$(docker stats --no-stream --format '{{.CPUPerc}}' "$NACOS_CONTAINER" 2>/dev/null | tr -d '%')
if [ -n "$cpu_percent" ]; then
output_result "NACOS_CPU_USAGE" "$cpu_percent"
fi
local mem_usage
mem_usage=$(docker stats --no-stream --format '{{.MemUsage}}' "$NACOS_CONTAINER" 2>/dev/null)
if [ -n "$mem_usage" ]; then
output_result "NACOS_MEMORY_USAGE" "$mem_usage"
fi
local mem_percent
mem_percent=$(docker stats --no-stream --format '{{.MemPerc}}' "$NACOS_CONTAINER" 2>/dev/null | tr -d '%')
if [ -n "$mem_percent" ]; then
output_result "NACOS_MEMORY_PERCENT" "$mem_percent"
fi
}
# ==================== 主检测流程 ====================
main() {
log_info "开始Nacos深度检测..."
# 检查容器状态(使用模糊匹配)
local matched_container=""
matched_container=$(docker ps --format "{{.Names}}" | grep -x "${NACOS_CONTAINER}" | head -1)
if [ -z "$matched_container" ] && [ -n "$NACOS_CONTAINER" ]; then
matched_container=$(docker ps --format "{{.Names}}" | grep -i "${NACOS_CONTAINER}" | head -1)
fi
if [ -z "$matched_container" ]; then
log_warn "Nacos容器未运行"
output_result "NACOS_CONTAINER_STATUS" "未运行"
return 1
fi
eval "NACOS_CONTAINER='${matched_container}'"
output_result "NACOS_CONTAINER_STATUS" "运行中 (${NACOS_CONTAINER})"
# 执行各项深度检测
check_nacos_version 2>/dev/null || true
check_nacos_services 2>/dev/null || true
check_nacos_instances 2>/dev/null || true
check_nacos_configs 2>/dev/null || true
check_nacos_raft 2>/dev/null || true
check_nacos_health_detail 2>/dev/null || true
check_nacos_memory_detail 2>/dev/null || true
check_nacos_logs 2>/dev/null || true
check_nacos_resources 2>/dev/null || true
log_info "Nacos深度检测完成"
}
main
#!/bin/bash
################################################################################
# 综合诊断检测模块
# 功能: 汇总所有检测异常,进行核心问题诊断和历史对比分析
# 作者: Claude Code
# 日期: 2026-07-20
################################################################################
# 获取脚本所在目录并加载依赖
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
# ==================== 检测函数 ====================
# 诊断系统负载
diagnose_system_load() {
local load1
load1=$(cat /proc/loadavg 2>/dev/null | awk '{print $1}')
if [ -n "$load1" ]; then
local cpu_count
cpu_count=$(nproc 2>/dev/null || echo "1")
local load_per_cpu
load_per_cpu=$(awk "BEGIN {printf \"%.2f\", $load1 / $cpu_count}")
output_result "DIAG_LOAD_1MIN" "$load1"
output_result "DIAG_LOAD_PER_CPU" "$load_per_cpu"
local level="正常"
if [ $(awk "BEGIN {print ($load_per_cpu > 4)}") -eq 1 ]; then
level="严重"
elif [ $(awk "BEGIN {print ($load_per_cpu > 2)}") -eq 1 ]; then
level="警告"
fi
output_result "DIAG_LOAD_LEVEL" "$level"
fi
}
# 诊断内存压力
diagnose_memory_pressure() {
local mem_info
mem_info=$(free -m 2>/dev/null | grep "Mem:")
if [ -n "$mem_info" ]; then
local total used free
total=$(echo "$mem_info" | awk '{print $2}')
used=$(echo "$mem_info" | awk '{print $3}')
free=$(echo "$mem_info" | awk '{print $4}')
local mem_usage
mem_usage=$(awk "BEGIN {printf \"%.1f\", ($used / $total) * 100}")
output_result "DIAG_MEMORY_USAGE" "${mem_usage}%"
output_result "DIAG_MEMORY_TOTAL" "${total}MB"
output_result "DIAG_MEMORY_USED" "${used}MB"
output_result "DIAG_MEMORY_FREE" "${free}MB"
local level="正常"
if [ $(awk "BEGIN {print ($mem_usage > 95)}") -eq 1 ]; then
level="严重"
elif [ $(awk "BEGIN {print ($mem_usage > 85)}") -eq 1 ]; then
level="警告"
fi
output_result "DIAG_MEMORY_LEVEL" "$level"
fi
}
# 诊断磁盘使用
diagnose_disk_usage() {
local disk_info
disk_info=$(df -h / 2>/dev/null | tail -1)
if [ -n "$disk_info" ]; then
local usage
usage=$(echo "$disk_info" | awk '{print $5}' | tr -d '%')
output_result "DIAG_DISK_USAGE" "${usage}%"
local level="正常"
if [ "$usage" -gt 95 ]; then
level="严重"
elif [ "$usage" -gt 85 ]; then
level="警告"
fi
output_result "DIAG_DISK_LEVEL" "$level"
fi
}
# 诊断Docker容器状态
diagnose_docker_status() {
if ! command -v docker &>/dev/null; then
return
fi
local total running stopped
total=$(docker ps -a --format "{{.Names}}" 2>/dev/null | wc -l)
running=$(docker ps --format "{{.Names}}" 2>/dev/null | wc -l)
stopped=$((total - running))
output_result "DIAG_DOCKER_TOTAL" "$total"
output_result "DIAG_DOCKER_RUNNING" "$running"
output_result "DIAG_DOCKER_STOPPED" "$stopped"
if [ "$stopped" -gt 5 ]; then
output_result "DIAG_DOCKER_LEVEL" "警告"
else
output_result "DIAG_DOCKER_LEVEL" "正常"
fi
}
# 诊断系统稳定性
diagnose_system_stability() {
local issues=0
# 检查OOM
if command -v dmesg &>/dev/null; then
local oom_count
oom_count=$(dmesg 2>/dev/null | grep -ci "out of memory" || echo "0")
if [ "$oom_count" -gt 0 ]; then
issues=$((issues + oom_count))
output_result "DIAG_OOM_ISSUES" "$oom_count"
fi
fi
# 检查磁盘错误
if command -v dmesg &>/dev/null; then
local disk_errors
disk_errors=$(dmesg 2>/dev/null | grep -ciE "I/O error|disk error" || echo "0")
if [ "$disk_errors" -gt 0 ]; then
issues=$((issues + disk_errors))
output_result "DIAG_DISK_ISSUES" "$disk_errors"
fi
fi
output_result "DIAG_TOTAL_ISSUES" "$issues"
if [ "$issues" -gt 10 ]; then
output_result "DIAG_STABILITY_LEVEL" "严重"
elif [ "$issues" -gt 0 ]; then
output_result "DIAG_STABILITY_LEVEL" "警告"
else
output_result "DIAG_STABILITY_LEVEL" "正常"
fi
}
# 诊断网络连通性
diagnose_network() {
local gateway
gateway=$(ip route 2>/dev/null | grep default | awk '{print $3}' | head -1)
if [ -n "$gateway" ]; then
output_result "DIAG_GATEWAY" "$gateway"
if ping -c 1 -W 2 "$gateway" &>/dev/null; then
output_result "DIAG_GATEWAY_STATUS" "可达"
else
output_result "DIAG_GATEWAY_STATUS" "不可达"
output_result "DIAG_NETWORK_LEVEL" "警告"
fi
fi
# 检查DNS解析
if host localhost &>/dev/null || nslookup localhost &>/dev/null; then
output_result "DIAG_DNS_STATUS" "正常"
else
output_result "DIAG_DNS_STATUS" "异常"
fi
}
# 综合健康评分
calculate_health_score() {
local score=100
# 内存扣分
local mem_info
mem_info=$(free -m 2>/dev/null | grep "Mem:")
if [ -n "$mem_info" ]; then
local total used
total=$(echo "$mem_info" | awk '{print $2}')
used=$(echo "$mem_info" | awk '{print $3}')
local mem_usage=$((used * 100 / total))
if [ "$mem_usage" -gt 95 ]; then
score=$((score - 20))
elif [ "$mem_usage" -gt 85 ]; then
score=$((score - 10))
fi
fi
# 磁盘扣分
local disk_usage
disk_usage=$(df / 2>/dev/null | tail -1 | awk '{print $5}' | tr -d '%')
if [ -n "$disk_usage" ]; then
if [ "$disk_usage" -gt 95 ]; then
score=$((score - 20))
elif [ "$disk_usage" -gt 85 ]; then
score=$((score - 10))
fi
fi
# 负载扣分
local load1
load1=$(cat /proc/loadavg 2>/dev/null | awk '{print $1}')
local cpu_count
cpu_count=$(nproc 2>/dev/null || echo "1")
if [ -n "$load1" ]; then
local load_ratio
load_ratio=$(awk "BEGIN {print $load1 / $cpu_count}")
if [ $(awk "BEGIN {print ($load_ratio > 4)}") -eq 1 ]; then
score=$((score - 15))
elif [ $(awk "BEGIN {print ($load_ratio > 2)}") -eq 1 ]; then
score=$((score - 5))
fi
fi
output_result "DIAG_HEALTH_SCORE" "$score"
if [ "$score" -ge 80 ]; then
output_result "DIAG_HEALTH_LEVEL" "正常"
elif [ "$score" -ge 60 ]; then
output_result "DIAG_HEALTH_LEVEL" "警告"
else
output_result "DIAG_HEALTH_LEVEL" "严重"
fi
}
# ==================== 主检测流程 ====================
main() {
log_info "开始综合诊断检测..."
set +e
diagnose_system_load 2>/dev/null || true
diagnose_memory_pressure 2>/dev/null || true
diagnose_disk_usage 2>/dev/null || true
diagnose_docker_status 2>/dev/null || true
diagnose_system_stability 2>/dev/null || true
diagnose_network 2>/dev/null || true
calculate_health_score 2>/dev/null || true
log_info "综合诊断检测完成"
}
main
\ No newline at end of file
#!/bin/bash
################################################################################
# 安全合规检测模块
# 功能: 检测系统安全状态、认证失败、异常账户、防火墙规则等
# 作者: Claude Code
# 日期: 2026-07-20
################################################################################
# 获取脚本所在目录并加载依赖
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_auth_failures() {
local auth_fail_count=0
if [ -f "/var/log/secure" ]; then
auth_fail_count=$(grep -c "Failed password" /var/log/secure 2>/dev/null || echo "0")
elif [ -f "/var/log/auth.log" ]; then
auth_fail_count=$(grep -c "Failed password" /var/log/auth.log 2>/dev/null || echo "0")
fi
output_result "AUTH_FAILURES_24H" "$auth_fail_count"
if [ "$auth_fail_count" -gt 1000 ]; then
output_result "AUTH_FAILURES_LEVEL" "严重"
elif [ "$auth_fail_count" -gt 100 ]; then
output_result "AUTH_FAILURES_LEVEL" "警告"
else
output_result "AUTH_FAILURES_LEVEL" "正常"
fi
}
# 检测当前登录用户
check_current_users() {
local current_users=""
local user_count="0"
if command -v who &>/dev/null; then
current_users=$(who 2>/dev/null)
if [ -n "$current_users" ]; then
user_count=$(echo "$current_users" | wc -l)
fi
fi
output_result "CURRENT_USERS_COUNT" "${user_count:-0}"
if [ -n "$current_users" ] && [ "$user_count" -gt 0 ]; then
local users_list
users_list=$(echo "$current_users" | cut -d' ' -f1 | tr '\n' ',' | sed 's/,$//' 2>/dev/null)
[ -n "$users_list" ] && output_result "CURRENT_USERS" "$users_list"
fi
}
# 检测防火墙规则
check_firewall_rules() {
if command -v firewall-cmd &>/dev/null; then
if systemctl is-active --quiet firewalld 2>/dev/null; then
output_result "FIREWALL_STATUS" "firewalld运行中"
else
output_result "FIREWALL_STATUS" "firewalld未运行"
fi
fi
if command -v iptables &>/dev/null; then
local iptables_rules
iptables_rules=$(iptables -L -n 2>/dev/null)
if [ -n "$iptables_rules" ]; then
output_result "IPTABLES_STATUS" "iptables已配置"
output_result "IPTABLES_RULES_COUNT" "$(echo "$iptables_rules" | grep -c "^Chain" || echo "0")"
fi
fi
local open_ports
open_ports=$(ss -tlnp 2>/dev/null | grep LISTEN | awk '{print $4}' | grep -oE '[0-9]+$' | sort -u | wc -l)
output_result "OPEN_PORTS_COUNT" "$open_ports"
}
# 检测异常账户(UID=0的非root账户)
check_abnormal_accounts() {
local abnormal_accounts=""
if [ -r "/etc/passwd" ]; then
while IFS=: read -r username x uid rest; do
if [ "$uid" = "0" ] && [ "$username" != "root" ]; then
if [ -z "$abnormal_accounts" ]; then
abnormal_accounts="$username"
else
abnormal_accounts="$abnormal_accounts,$username"
fi
fi
done < /etc/passwd 2>/dev/null || true
fi
if [ -n "$abnormal_accounts" ]; then
output_result "ABNORMAL_ACCOUNTS" "$abnormal_accounts"
output_result "ABNORMAL_ACCOUNTS_LEVEL" "严重"
else
output_result "ABNORMAL_ACCOUNTS" "无"
output_result "ABNORMAL_ACCOUNTS_LEVEL" "正常"
fi
}
# 检测SSH配置安全检查
check_ssh_security() {
local ssh_config="/etc/ssh/sshd_config"
if [ -f "$ssh_config" ]; then
local permit_root
permit_root=$(grep -E "^PermitRootLogin" "$ssh_config" 2>/dev/null | grep -v "^#" | awk '{print $2}')
output_result "SSH_PERMIT_ROOT" "${permit_root:-未设置}"
local password_auth
password_auth=$(grep -E "^PasswordAuthentication" "$ssh_config" 2>/dev/null | grep -v "^#" | awk '{print $2}')
output_result "SSH_PASSWORD_AUTH" "${password_auth:-未设置}"
local ssh_port
ssh_port=$(grep -E "^Port" "$ssh_config" 2>/dev/null | grep -v "^#" | awk '{print $2}')
output_result "SSH_PORT" "${ssh_port:-22}"
if [ "$permit_root" = "yes" ]; then
output_result "SSH_ROOT_LOGIN_LEVEL" "严重"
else
output_result "SSH_ROOT_LOGIN_LEVEL" "正常"
fi
fi
}
# 检测开放端口详情
check_open_ports_detail() {
local tcp_ports
tcp_ports=$(ss -tlnp 2>/dev/null | grep LISTEN | awk '{print $4}' | grep -oE '[0-9]+$' | sort -nu | tr '\n' ',' | sed 's/,$//')
output_result "OPEN_TCP_PORTS" "$tcp_ports"
# 高风险端口
local high_risk_ports="23,135,139,445,1433,3389,5900,5901"
local found_risk_ports=""
for port in ${high_risk_ports//,/ }; do
if ss -tlnp 2>/dev/null | grep -q ":$port "; then
[ -z "$found_risk_ports" ] && found_risk_ports="$port" || found_risk_ports="$found_risk_ports,$port"
fi
done
if [ -n "$found_risk_ports" ]; then
output_result "HIGH_RISK_PORTS" "$found_risk_ports"
output_result "HIGH_RISK_PORTS_LEVEL" "警告"
else
output_result "HIGH_RISK_PORTS" "无"
output_result "HIGH_RISK_PORTS_LEVEL" "正常"
fi
}
# 检测暴力破解IP
check_brute_force_ips() {
local brute_force_ips=""
if [ -f "/var/log/secure" ]; then
brute_force_ips=$(grep "Failed password" /var/log/secure 2>/dev/null | grep -oE 'from [0-9.]+' | cut -d' ' -f2 | sort | uniq -c | sort -rn | head -5)
elif [ -f "/var/log/auth.log" ]; then
brute_force_ips=$(grep "Failed password" /var/log/auth.log 2>/dev/null | grep -oE 'from [0-9.]+' | cut -d' ' -f2 | sort | uniq -c | sort -rn | head -5)
fi
if [ -n "$brute_force_ips" ]; then
local max_attempts
max_attempts=$(echo "$brute_force_ips" | head -1 | awk '{print $1}')
output_result "MAX_LOGIN_FAILURES" "$max_attempts"
output_result "BRUTE_FORCE_IPS" "$(echo "$brute_force_ips" | sed 's/ /:/g' | tr '\n' ',' | sed 's/,$//')"
if [ "$max_attempts" -gt 100 ]; then
output_result "BRUTE_FORCE_LEVEL" "严重"
elif [ "$max_attempts" -gt 20 ]; then
output_result "BRUTE_FORCE_LEVEL" "警告"
else
output_result "BRUTE_FORCE_LEVEL" "正常"
fi
else
output_result "MAX_LOGIN_FAILURES" "0"
output_result "BRUTE_FORCE_LEVEL" "正常"
fi
}
# ==================== 主检测流程 ====================
main() {
log_info "开始安全合规检测..."
set +e
check_auth_failures 2>/dev/null || true
check_current_users 2>/dev/null || true
check_firewall_rules 2>/dev/null || true
check_abnormal_accounts 2>/dev/null || true
check_ssh_security 2>/dev/null || true
check_open_ports_detail 2>/dev/null || true
check_brute_force_ips 2>/dev/null || true
log_info "安全合规检测完成"
}
main
\ No newline at end of file
#!/bin/bash
################################################################################
# 系统日志检测模块
# 功能: 检测内核错误、磁盘错误、服务崩溃、系统资源耗尽等日志问题
# 作者: Claude Code
# 日期: 2026-07-20
################################################################################
# 获取脚本所在目录并加载依赖
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_kernel_errors() {
local kernel_errors=0
if command -v dmesg &>/dev/null; then
kernel_errors=$(dmesg 2>/dev/null | grep -iE "error|fail|timeout" | grep -v "ACPI" | wc -l || echo "0")
fi
output_result "KERNEL_ERRORS_24H" "${kernel_errors:-0}"
if [ "$kernel_errors" -gt 100 ]; then
output_result "KERNEL_ERRORS_LEVEL" "严重"
elif [ "$kernel_errors" -gt 10 ]; then
output_result "KERNEL_ERRORS_LEVEL" "警告"
else
output_result "KERNEL_ERRORS_LEVEL" "正常"
fi
}
# 检测磁盘错误
check_disk_errors() {
local disk_errors=0
if command -v dmesg &>/dev/null; then
disk_errors=$(dmesg 2>/dev/null | grep -ciE "I/O error|disk error|ata error|sd.*error|nvme.*error|filesystem error" || echo "0")
fi
output_result "DISK_ERRORS_24H" "${disk_errors:-0}"
if [ "$disk_errors" -gt 10 ]; then
output_result "DISK_ERRORS_LEVEL" "严重"
elif [ "$disk_errors" -gt 0 ]; then
output_result "DISK_ERRORS_LEVEL" "警告"
else
output_result "DISK_ERRORS_LEVEL" "正常"
fi
}
# 检测内核panic/oops
check_kernel_panic() {
local panic_count=0
local oops_count=0
if command -v dmesg &>/dev/null; then
panic_count=$(dmesg 2>/dev/null | grep -ci "kernel panic" || echo "0")
oops_count=$(dmesg 2>/dev/null | grep -ci "kernel oops\|BUG:" || echo "0")
fi
output_result "KERNEL_PANIC_COUNT" "$panic_count"
output_result "KERNEL_OOPS_COUNT" "$oops_count"
if [ "$panic_count" -gt 0 ]; then
output_result "KERNEL_STABILITY_LEVEL" "严重"
elif [ "$oops_count" -gt 5 ]; then
output_result "KERNEL_STABILITY_LEVEL" "警告"
else
output_result "KERNEL_STABILITY_LEVEL" "正常"
fi
}
# 检测服务崩溃重启记录
check_service_crashes() {
local crash_count=0
local crashed_services=""
if command -v docker &>/dev/null; then
local restarted_containers
restarted_containers=$(docker ps -a --format "{{.Names}}: {{.RestartCount}}" 2>/dev/null | grep -v ": 0$" | grep -v ": $")
if [ -n "$restarted_containers" ]; then
crash_count=$(echo "$restarted_containers" | wc -l)
crashed_services=$(echo "$restarted_containers" | tr '\n' ',' | sed 's/,$//')
fi
fi
output_result "SERVICE_CRASH_COUNT" "$crash_count"
if [ -n "$crashed_services" ]; then
output_result "CRASHED_SERVICES" "$crashed_services"
fi
if [ "$crash_count" -gt 5 ]; then
output_result "SERVICE_STABILITY_LEVEL" "严重"
elif [ "$crash_count" -gt 0 ]; then
output_result "SERVICE_STABILITY_LEVEL" "警告"
else
output_result "SERVICE_STABILITY_LEVEL" "正常"
fi
}
# 检测systemd服务失败列表
check_systemd_failures() {
if ! command -v systemctl &>/dev/null; then
return
fi
local failed_services
failed_services=$(systemctl list-units --state=failed --no-legend 2>/dev/null | awk '{print $1}' | tr '\n' ',' | sed 's/,$//')
if [ -n "$failed_services" ]; then
local failed_count
failed_count=$(echo "$failed_services" | tr ',' '\n' | wc -l)
output_result "SYSTEMD_FAILED_COUNT" "$failed_count"
output_result "SYSTEMD_FAILED_SERVICES" "$failed_services"
output_result "SYSTEMD_FAILED_LEVEL" "严重"
else
output_result "SYSTEMD_FAILED_COUNT" "0"
output_result "SYSTEMD_FAILED_LEVEL" "正常"
fi
}
# 检测OOM Killer记录
check_oom_killer() {
local oom_count=0
if command -v dmesg &>/dev/null; then
oom_count=$(dmesg 2>/dev/null | grep -ci "out of memory" || echo "0")
fi
output_result "OOM_KILLER_COUNT" "$oom_count"
if [ "$oom_count" -gt 0 ]; then
output_result "OOM_LEVEL" "严重"
else
output_result "OOM_LEVEL" "正常"
fi
}
# 检测日志文件大小
check_log_file_sizes() {
local large_logs=""
for log_file in /var/log/messages /var/log/syslog /var/log/kern.log; do
if [ -f "$log_file" ]; then
local log_size
log_size=$(du -m "$log_file" 2>/dev/null | awk '{print $1}')
if [ "$log_size" -gt 500 ]; then
local log_name
log_name=$(basename "$log_file")
large_logs="${large_logs}${log_name}:${log_size}MB,"
fi
fi
done
large_logs=$(echo "$large_logs" | sed 's/,$//')
if [ -n "$large_logs" ]; then
output_result "LARGE_LOG_FILES" "$large_logs"
output_result "LARGE_LOG_FILES_LEVEL" "警告"
else
output_result "LARGE_LOG_FILES" "无"
output_result "LARGE_LOG_FILES_LEVEL" "正常"
fi
}
# 检测/var/log/messages
check_messages_log() {
local messages_file="/var/log/messages"
if [ ! -f "$messages_file" ]; then
if [ -f "/var/log/syslog" ]; then
messages_file="/var/log/syslog"
else
return
fi
fi
local error_count warn_count
error_count=$(grep -c "ERROR" "$messages_file" 2>/dev/null || echo "0")
warn_count=$(grep -c "WARN" "$messages_file" 2>/dev/null || echo "0")
output_result "MESSAGES_ERRORS_COUNT" "$error_count"
output_result "MESSAGES_WARNS_COUNT" "$warn_count"
local log_size
log_size=$(du -h "$messages_file" 2>/dev/null | awk '{print $1}')
output_result "MESSAGES_LOG_SIZE" "$log_size"
}
# ==================== 主检测流程 ====================
main() {
log_info "开始系统日志检测..."
set +e
check_kernel_errors 2>/dev/null || true
check_disk_errors 2>/dev/null || true
check_kernel_panic 2>/dev/null || true
check_service_crashes 2>/dev/null || true
check_systemd_failures 2>/dev/null || true
check_oom_killer 2>/dev/null || true
check_log_file_sizes 2>/dev/null || true
check_messages_log 2>/dev/null || true
log_info "系统日志检测完成"
}
main
\ No newline at end of file
#!/bin/bash
################################################################################
# 时间同步检测模块
# 功能: 检测NTP同步状态、时钟偏差、SSL证书有效期等
# 作者: Claude Code
# 日期: 2026-07-20
################################################################################
# 获取脚本所在目录并加载依赖
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
# ==================== 检测函数 ====================
# 检测NTP同步状态
check_ntp_status() {
if command -v timedatectl &>/dev/null; then
local timedate_output
timedate_output=$(timedatectl status 2>/dev/null)
if echo "$timedate_output" | grep -q "NTP service: active"; then
output_result "NTP_SERVICE_STATUS" "运行中"
elif echo "$timedate_output" | grep -q "NTP enabled: yes"; then
output_result "NTP_SERVICE_STATUS" "已启用"
else
output_result "NTP_SERVICE_STATUS" "未启用"
output_result "NTP_SERVICE_LEVEL" "警告"
fi
if echo "$timedate_output" | grep -q "System clock synchronized: yes"; then
output_result "SYSTEM_CLOCK_SYNC" "已同步"
else
output_result "SYSTEM_CLOCK_SYNC" "未同步"
output_result "SYSTEM_CLOCK_SYNC_LEVEL" "警告"
fi
fi
# 检查NTP守护进程
if systemctl is-active --quiet chronyd 2>/dev/null; then
output_result "NTP_DAEMON" "chronyd"
elif systemctl is-active --quiet ntpd 2>/dev/null; then
output_result "NTP_DAEMON" "ntpd"
elif systemctl is-active --quiet systemd-timesyncd 2>/dev/null; then
output_result "NTP_DAEMON" "systemd-timesyncd"
fi
}
# 检测时钟同步源
check_ntp_sources() {
local sources=""
local current_source=""
if command -v chronyc &>/dev/null; then
local chronyc_sources
chronyc_sources=$(chronyc sources 2>/dev/null)
if [ -n "$chronyc_sources" ]; then
sources=$(echo "$chronyc_sources" | grep "^[\*\+\#]" | awk '{print $2}' | tr '\n' ',' | sed 's/,$//')
current_source=$(echo "$chronyc_sources" | grep "^\*" | awk '{print $2}' | head -1)
output_result "NTP_SOURCES" "$sources"
if [ -n "$current_source" ]; then
output_result "NTP_CURRENT_SOURCE" "$current_source"
fi
fi
fi
if [ -z "$sources" ] && command -v ntpq &>/dev/null; then
local ntpq_output
ntpq_output=$(ntpq -p 2>/dev/null)
if [ -n "$ntpq_output" ]; then
sources=$(echo "$ntpq_output" | grep "^[\*\+\+\#]" | awk '{print $1}' | tr '\n' ',' | sed 's/,$//')
current_source=$(echo "$ntpq_output" | grep "^\*" | awk '{print $1}' | head -1)
output_result "NTP_SOURCES" "$sources"
if [ -n "$current_source" ]; then
output_result "NTP_CURRENT_SOURCE" "$current_source"
fi
fi
fi
}
# 检测时钟偏差
check_clock_offset() {
local offset_ms="未知"
local offset_level="正常"
if command -v chronyc &>/dev/null; then
local chronyc_tracking
chronyc_tracking=$(chronyc tracking 2>/dev/null)
if [ -n "$chronyc_tracking" ]; then
offset_ms=$(echo "$chronyc_tracking" | grep "RMS offset" | awk '{print $4}')
if [ -n "$offset_ms" ] && [ "$offset_ms" != "未知" ]; then
output_result "NTP_OFFSET_MS" "$offset_ms"
local offset_abs
offset_abs=$(awk "BEGIN {print ($offset_ms < 0) ? -$offset_ms : $offset_ms}")
if [ "$offset_abs" -gt 5000000 ]; then
offset_level="严重"
elif [ "$offset_abs" -gt 1000000 ]; then
offset_level="警告"
fi
fi
fi
fi
output_result "NTP_OFFSET_LEVEL" "$offset_level"
}
# 检测系统时间
check_system_time() {
local system_date
system_date=$(date 2>/dev/null)
output_result "SYSTEM_DATETIME" "$system_date"
local system_timestamp
system_timestamp=$(date +%s 2>/dev/null)
output_result "SYSTEM_TIMESTAMP" "$system_timestamp"
local timezone
timezone=$(timedatectl status 2>/dev/null | grep "Time zone" | awk '{print $3}')
[ -n "$timezone" ] && output_result "SYSTEM_TIMEZONE" "$timezone"
}
# 检测HTTPS证书有效期
check_https_cert_expiry() {
local cert_files=""
for cert_path in /etc/nginx/ssl/*.crt /etc/nginx/certs/*.crt /etc/ssl/certs/*.crt; do
if [ -f "$cert_path" ]; then
cert_files="${cert_files}${cert_path},"
fi
done
cert_files=$(echo "$cert_files" | sed 's/,$//')
if [ -n "$cert_files" ]; then
local min_days=9999
for cert in ${cert_files//,/ }; do
if [ -f "$cert" ]; then
local expiry_date
expiry_date=$(openssl x509 -in "$cert" -noout -enddate 2>/dev/null | cut -d= -f2)
if [ -n "$expiry_date" ]; then
local expiry_timestamp
expiry_timestamp=$(date -d "$expiry_date" +%s 2>/dev/null)
if [ -n "$expiry_timestamp" ]; then
local current_timestamp
current_timestamp=$(date +%s)
local days_left=$(( (expiry_timestamp - current_timestamp) / 86400 ))
if [ "$days_left" -lt "$min_days" ]; then
min_days=$days_left
fi
fi
fi
fi
done
if [ "$min_days" -lt 9999 ]; then
output_result "HTTPS_CERT_MIN_DAYS" "$min_days"
if [ "$min_days" -le 7 ]; then
output_result "HTTPS_CERT_LEVEL" "严重"
elif [ "$min_days" -le 30 ]; then
output_result "HTTPS_CERT_LEVEL" "警告"
else
output_result "HTTPS_CERT_LEVEL" "正常"
fi
fi
else
output_result "HTTPS_CERT_STATUS" "未找到证书文件"
fi
}
# 检测系统运行时间
check_uptime() {
local uptime_seconds
uptime_seconds=$(cat /proc/uptime 2>/dev/null | awk '{print $1}' | cut -d. -f1)
if [ -n "$uptime_seconds" ]; then
local uptime_days
uptime_days=$((uptime_seconds / 86400))
output_result "SYSTEM_UPTIME_DAYS" "$uptime_days"
fi
}
# ==================== 主检测流程 ====================
main() {
log_info "开始时间同步检测..."
set +e
check_ntp_status 2>/dev/null || true
check_ntp_sources 2>/dev/null || true
check_clock_offset 2>/dev/null || true
check_system_time 2>/dev/null || true
check_https_cert_expiry 2>/dev/null || true
check_uptime 2>/dev/null || true
log_info "时间同步检测完成"
}
main
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论