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

feat(service-monitor): 新增 10 个检测模块

系统检测(5 个):
- 05_oom_check: OOM 和内核异常检测
- 06_process_check: 进程检测
- 07_network_check: 网络检测
- 11_scheduled_tasks: 计划任务检测
- 12_port_check: 端口检测

服务深度检测(3 个):
- 21_docker_deep: Docker 深度检测
- 23_mysql_depth: MySQL 深度检测
- 25_redis_depth: Redis 深度检测

业务容器监测(2 个):
- 37_ustorage_check: UStorage 容器监测
- 38_utracker_check: UTracker 容器监测

- check_modules.py: ALL_MODULES 从 7→17 个
- display_names.py: 新增 ~150 个 KEY 中文显示名
- config.sh.template: 新增 ustorge/utracker 容器匹配模式
Co-Authored-By: 's avatarClaude <noreply@anthropic.com>
上级 b0b61d2e
...@@ -21,6 +21,8 @@ CONTAINERS[nginx]="nginx" ...@@ -21,6 +21,8 @@ CONTAINERS[nginx]="nginx"
CONTAINERS[nacos]="nacos" CONTAINERS[nacos]="nacos"
CONTAINERS[python]="python" CONTAINERS[python]="python"
CONTAINERS[python_voice]="python_voice" CONTAINERS[python_voice]="python_voice"
CONTAINERS[ustorage]="ustorage|storage"
CONTAINERS[utracker]="utracker|tracker"
# ==================== 凭据(占位符,渲染时注入;值由 Python 端做 shell 安全引用) ==================== # ==================== 凭据(占位符,渲染时注入;值由 Python 端做 shell 安全引用) ====================
MYSQL_PASSWORD=__MYSQL_PASSWORD__ MYSQL_PASSWORD=__MYSQL_PASSWORD__
......
#!/bin/bash
################################################################################
# Docker深度检测模块
# 功能: 深度检测Docker镜像、网络、卷、事件、系统信息等
# 作者: 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
# ==================== 深度检测函数 ====================
# 检测Docker系统信息
check_docker_system_info() {
local docker_version server_version storage_driver
docker_version=$(docker version --format '{{.Server.Version}}' 2>/dev/null)
server_version=$(docker version --format '{{.Server.APIVersion}}' 2>/dev/null)
storage_driver=$(docker info --format '{{.Driver}}' 2>/dev/null)
if [ -n "$docker_version" ]; then
output_result "DOCKER_VERSION" "$docker_version"
else
output_result "DOCKER_VERSION" "获取失败"
fi
if [ -n "$server_version" ]; then
output_result "DOCKER_API_VERSION" "$server_version"
fi
if [ -n "$storage_driver" ]; then
output_result "DOCKER_STORAGE_DRIVER" "$storage_driver"
fi
}
# 检测Docker镜像列表
check_docker_images() {
local image_count dangling_count
image_count=$(docker images -q 2>/dev/null | wc -l)
dangling_count=$(docker images -f "dangling=true" -q 2>/dev/null | wc -l)
output_result "DOCKER_IMAGES_COUNT" "$image_count"
output_result "DOCKER_IMAGES_DANGLING" "$dangling_count"
# 获取TOP5最大镜像
local top_images
top_images=$(docker images --format "{{.Repository}}:{{.Tag}}\t{{.Size}}" 2>/dev/null | sort -k2 -h | tail -5 | tr '\n' '|' | sed 's/|$//')
if [ -n "$top_images" ]; then
output_result "DOCKER_IMAGES_TOP5" "$top_images"
else
output_result "DOCKER_IMAGES_TOP5" "无"
fi
}
# 检测Docker网络详情
check_docker_network_detail() {
local network_count bridge_count overlay_count
network_count=$(docker network ls 2>/dev/null | grep -c "^" || echo "0")
network_count=$((network_count - 1))
bridge_count=$(docker network ls 2>/dev/null | grep -c "bridge" || echo "0")
overlay_count=$(docker network ls 2>/dev/null | grep -c "overlay" || echo "0")
output_result "DOCKER_NETWORK_COUNT" "$network_count"
output_result "DOCKER_NETWORK_BRIDGE" "$bridge_count"
output_result "DOCKER_NETWORK_OVERLAY" "$overlay_count"
# 获取网络列表
local network_list
network_list=$(docker network ls --format "{{.Name}}\t{{.Driver}}\t{{.Scope}}" 2>/dev/null | tr '\n' '|' | sed 's/|$//')
if [ -n "$network_list" ]; then
output_result "DOCKER_NETWORK_LIST" "$network_list"
fi
}
# 检测Docker卷
check_docker_volumes() {
local volume_count unused_count
volume_count=$(docker volume ls -q 2>/dev/null | wc -l)
output_result "DOCKER_VOLUMES_COUNT" "$volume_count"
# 获取卷列表
local volume_list
volume_list=$(docker volume ls --format "{{.Name}}\t{{.Driver}}" 2>/dev/null | tr '\n' '|' | sed 's/|$//')
if [ -n "$volume_list" ]; then
output_result "DOCKER_VOLUMES_LIST" "$volume_list"
fi
}
# 检测容器资源限制
check_container_limits() {
for key in "${!CONTAINERS[@]}"; do
local container_name="${CONTAINERS[$key]}"
if ! docker ps -a --format "{{.Names}}" | grep -q "^${container_name}$"; then
continue
fi
# 获取CPU限制
local cpu_quota cpu_period
cpu_quota=$(docker inspect --format='{{.HostConfig.CpuQuota}}' "$container_name" 2>/dev/null)
cpu_period=$(docker inspect --format='{{.HostConfig.CpuPeriod}}' "$container_name" 2>/dev/null)
if [ -n "$cpu_quota" ] && [ "$cpu_quota" != "0" ]; then
local cpu_limit=$((cpu_quota * 100 / cpu_period))
output_result "LIMIT_${container_name}_CPU" "${cpu_limit}%"
else
output_result "LIMIT_${container_name}_CPU" "无限制"
fi
# 获取内存限制
local memory_limit
memory_limit=$(docker inspect --format='{{.HostConfig.Memory}}' "$container_name" 2>/dev/null)
if [ -n "$memory_limit" ] && [ "$memory_limit" != "0" ]; then
local memory_mb=$((memory_limit / 1024 / 1024))
output_result "LIMIT_${container_name}_MEMORY" "${memory_mb}MB"
else
output_result "LIMIT_${container_name}_MEMORY" "无限制"
fi
done
}
# 检测容器进程详情
check_container_processes() {
for key in "mysql" "redis" "emqx" "java"; do
local container_name="${CONTAINERS[$key]}"
if [ -z "$container_name" ]; then
continue
fi
if ! docker ps --format "{{.Names}}" | grep -q "^${container_name}$"; then
continue
fi
# 获取容器内进程数
local process_count
process_count=$(docker exec "$container_name" ps aux 2>/dev/null | wc -l)
process_count=$((process_count - 1))
if [ -n "$process_count" ] && [ "$process_count" -gt 0 ]; then
output_result "PROCESSES_${container_name}" "$process_count"
fi
done
}
# 检测容器文件系统使用
check_container_fs_usage() {
for key in "${!CONTAINERS[@]}"; do
local container_name="${CONTAINERS[$key]}"
if ! docker ps --format "{{.Names}}" | grep -q "^${container_name}$"; then
continue
fi
# 获取容器根文件系统大小
local size_rw size_rootfs
size_rw=$(docker inspect --format='{{.SizeRw}}' "$container_name" 2>/dev/null)
size_rootfs=$(docker inspect --format='{{.SizeRootFs}}' "$container_name" 2>/dev/null)
if [ -n "$size_rw" ] && [ "$size_rw" != "0" ]; then
local rw_mb=$((size_rw / 1024 / 1024))
output_result "FS_${container_name}_RW" "${rw_mb}MB"
fi
if [ -n "$size_rootfs" ] && [ "$size_rootfs" != "0" ]; then
local rootfs_mb=$((size_rootfs / 1024 / 1024))
output_result "FS_${container_name}_ROOT" "${rootfs_mb}MB"
fi
done
}
# 检测Docker事件(最近的错误和警告)
check_docker_events() {
# 获取最近1小时的事件
local error_events warn_events
error_events=$(docker events --since 1h --until 1m --format '{{$line}}' 2>/dev/null | grep -i "error" | wc -l)
warn_events=$(docker events --since 1h --until 1m --format '{{$line}}' 2>/dev/null | grep -E "warn|kill|die" | wc -l)
output_result "DOCKER_EVENTS_ERROR" "$error_events"
output_result "DOCKER_EVENTS_WARN" "$warn_events"
if [ "$error_events" -gt 0 ]; then
output_result "DOCKER_EVENTS_LEVEL" "严重"
elif [ "$warn_events" -gt 0 ]; then
output_result "DOCKER_EVENTS_LEVEL" "警告"
else
output_result "DOCKER_EVENTS_LEVEL" "正常"
fi
}
# 检测容器重启历史
check_container_restart_history() {
for key in "${!CONTAINERS[@]}"; do
local container_name="${CONTAINERS[$key]}"
if ! docker ps -a --format "{{.Names}}" | grep -q "^${container_name}$"; then
continue
fi
# 获取重启次数
local restart_count
restart_count=$(docker inspect --format='{{.RestartCount}}' "$container_name" 2>/dev/null)
if [ -n "$restart_count" ]; then
output_result "RESTART_COUNT_${container_name}" "$restart_count"
fi
# 获取上次重启时间
local restarted_at
restarted_at=$(docker inspect --format='{{.State.StartedAt}}' "$container_name" 2>/dev/null)
if [ -n "$restarted_at" ]; then
output_result "RESTART_TIME_${container_name}" "$restarted_at"
fi
done
}
# 检测Docker守护进程资源
check_docker_daemon_resources() {
# 获取Docker守护进程的CPU和内存使用
local docker_pid
docker_pid=$(pgrep dockerd | head -1)
if [ -n "$docker_pid" ]; then
local docker_cpu docker_mem
docker_cpu=$(ps -p "$docker_pid" -o %cpu --no-headers 2>/dev/null | tr -d ' ')
docker_mem=$(ps -p "$docker_pid" -o %mem --no-headers 2>/dev/null | tr -d ' ')
if [ -n "$docker_cpu" ]; then
output_result "DOCKER_DAEMON_CPU" "${docker_cpu}%"
fi
if [ -n "$docker_mem" ]; then
output_result "DOCKER_DAEMON_MEM" "${docker_mem}%"
fi
fi
}
# 检测容器挂载点
check_container_mounts() {
for key in "${!CONTAINERS[@]}"; do
local container_name="${CONTAINERS[$key]}"
if ! docker ps --format "{{.Names}}" | grep -q "^${container_name}$"; then
continue
fi
# 获取挂载点数量
local mount_count
mount_count=$(docker inspect --format='{{len .Mounts}}' "$container_name" 2>/dev/null)
if [ -n "$mount_count" ] && [ "$mount_count" -gt 0 ]; then
output_result "MOUNTS_${container_name}_COUNT" "$mount_count"
# 获取挂载点列表
local mounts
mounts=$(docker inspect --format='{{range .Mounts}}{{.Source}}:{{.Destination}}|{{end}}' "$container_name" 2>/dev/null | sed 's/|$//')
if [ -n "$mounts" ]; then
output_result "MOUNTS_${container_name}_LIST" "$mounts"
fi
fi
done
}
# 检测容器环境变量(安全检查)
check_container_env() {
# 检查是否有明文密码等敏感信息
for key in "mysql" "redis"; do
local container_name="${CONTAINERS[$key]}"
if [ -z "$container_name" ]; then
continue
fi
if ! docker ps --format "{{.Names}}" | grep -q "^${container_name}$"; then
continue
fi
# 获取环境变量数量
local env_count
env_count=$(docker inspect --format='{{len .Config.Env}}' "$container_name" 2>/dev/null)
if [ -n "$env_count" ]; then
output_result "ENV_${container_name}_COUNT" "$env_count"
fi
done
}
# 检测Docker构建缓存
check_docker_build_cache() {
# 获取构建缓存大小(通过docker system df)
local build_cache
build_cache=$(docker system df --format "{{.BuildCache}}" 2>/dev/null | grep -v "Build Cache" | head -1)
if [ -n "$build_cache" ]; then
output_result "DOCKER_BUILD_CACHE" "$build_cache"
fi
}
# ==================== 主检测流程 ====================
main() {
log_info "开始Docker深度检测..."
# 检查Docker是否可用
if ! command -v docker &> /dev/null; then
log_error "Docker未安装"
return 1
fi
# 执行各项深度检测
check_docker_system_info
check_docker_images
check_docker_network_detail
check_docker_volumes
check_container_limits
check_container_processes
check_container_fs_usage
check_docker_events
check_container_restart_history
check_docker_daemon_resources
check_container_mounts
check_container_env
check_docker_build_cache
log_info "Docker深度检测完成"
}
# 执行主函数
main
#!/bin/bash
# MySQL深度检测脚本
# 使用方法: ./mysql_depth_check.sh
MYSQL_PASSWORD="dNrprU&2S"
CONTAINER="umysql"
# 运行时间
UPTIME=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW STATUS LIKE 'Uptime';" 2>&1 | tail -1 | awk '{print $2}')
if [ -n "$UPTIME" ] && [ "$UPTIME" -gt 0 ]; then
UPTIME_DAYS=$((UPTIME / 86400))
echo "UPTIME_DAYS:$UPTIME_DAYS"
else
echo "UPTIME_DAYS:N/A"
fi
# 连接数
THREADS_CONNECTED=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW STATUS LIKE 'Threads_connected';" 2>&1 | tail -1 | awk '{print $2}')
MAX_CONNECTIONS=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW VARIABLES LIKE 'max_connections';" 2>&1 | tail -1 | awk '{print $2}')
if [ -n "$THREADS_CONNECTED" ] && [ -n "$MAX_CONNECTIONS" ] && [ "$MAX_CONNECTIONS" -gt 0 ]; then
CONN_PERCENT=$(awk "BEGIN {printf \"%.1f\", $THREADS_CONNECTED*100/$MAX_CONNECTIONS}")
echo "CONNECTIONS:$THREADS_CONNECTED/$MAX_CONNECTIONS/$CONN_PERCENT"
else
echo "CONNECTIONS:N/A"
fi
# 慢查询
SLOW_QUERIES=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW GLOBAL STATUS LIKE 'Slow_queries';" 2>&1 | tail -1 | awk '{print $2}')
if [ -n "$SLOW_QUERIES" ]; then
echo "SLOW_QUERIES:$SLOW_QUERIES"
else
echo "SLOW_QUERIES:0"
fi
# QPS统计
QUESTIONS=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW GLOBAL STATUS LIKE 'Questions';" 2>&1 | tail -1 | awk '{print $2}')
UPTIME=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW STATUS LIKE 'Uptime';" 2>&1 | tail -1 | awk '{print $2}')
if [ -n "$QUESTIONS" ] && [ -n "$UPTIME" ] && [ "$UPTIME" -gt 0 ]; then
QPS=$(awk "BEGIN {printf \"%.2f\", $QUESTIONS/$UPTIME}")
echo "QPS:$QPS"
else
echo "QPS:N/A"
fi
# TPS统计
COM_COMMIT=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW GLOBAL STATUS LIKE 'Com_commit';" 2>&1 | tail -1 | awk '{print $2}')
COM_ROLLBACK=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW GLOBAL STATUS LIKE 'Com_rollback';" 2>&1 | tail -1 | awk '{print $2}')
if [ -n "$COM_COMMIT" ] && [ -n "$COM_ROLLBACK" ] && [ -n "$UPTIME" ] && [ "$UPTIME" -gt 0 ]; then
TOTAL_TRANS=$((COM_COMMIT + COM_ROLLBACK))
TPS=$(awk "BEGIN {printf \"%.2f\", $TOTAL_TRANS/$UPTIME}")
echo "TPS:$TPS"
else
echo "TPS:N/A"
fi
# 死锁检测
DEADLOCK_OUTPUT=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW GLOBAL STATUS LIKE 'Innodb_deadlocks';" 2>&1 | grep -v Warning)
if [ -n "$DEADLOCK_OUTPUT" ] && [ "$DEADLOCK_OUTPUT" != "" ]; then
DEADLOCKS=$(echo "$DEADLOCK_OUTPUT" | awk 'NF>=2 {print $2}')
if [ -z "$DEADLOCKS" ]; then
DEADLOCKS=0
fi
else
DEADLOCKS=0
fi
echo "DEADLOCKS:$DEADLOCKS"
# Buffer Pool命中率
BUFFER_POOL_RESULT=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -e "SELECT (1 - (SELECT variable_value FROM performance_schema.global_status WHERE variable_name = 'Innodb_buffer_pool_reads') / (SELECT variable_value FROM performance_schema.global_status WHERE variable_name = 'Innodb_buffer_pool_read_requests')) * 100 AS hit_ratio;" 2>&1 | grep -v Warning | tail -1)
if [ -n "$BUFFER_POOL_RESULT" ] && [[ "$BUFFER_POOL_RESULT" =~ ^[0-9]+\.?[0-9]*$ ]]; then
HIT_RATE=$(awk "BEGIN {printf \"%.2f\", $BUFFER_POOL_RESULT}")
echo "BUFFER_POOL_HIT_RATE:$HIT_RATE"
else
echo "BUFFER_POOL_HIT_RATE:N/A"
fi
# 表缓存命中率
OPEN_TABLES=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW GLOBAL STATUS LIKE 'Open_tables';" 2>/dev/null | awk '{print $2}')
OPENED_TABLES=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW GLOBAL STATUS LIKE 'Opened_tables';" 2>/dev/null | awk '{print $2}')
# 验证数值
if [[ "$OPEN_TABLES" =~ ^[0-9]+$ ]] && [[ "$OPENED_TABLES" =~ ^[0-9]+$ ]]; then
if [ "$OPENED_TABLES" -eq 0 ]; then
# 没有重新打开过表,缓存命中100%
echo "CACHE_HIT_RATE:100.00"
elif [ "$OPEN_TABLES" -gt 0 ]; then
# 表缓存命中率 = Open_tables / (Open_tables + Opened_tables) × 100
# Opened_tables表示需要重新打开表的次数(缓存未命中)
TOTAL_OPENS=$((OPEN_TABLES + OPENED_TABLES))
CACHE_HIT_RATE=$(awk "BEGIN {printf \"%.2f\", ($OPEN_TABLES * 100) / $TOTAL_OPENS}")
echo "CACHE_HIT_RATE:$CACHE_HIT_RATE"
else
echo "CACHE_HIT_RATE:N/A"
fi
else
echo "CACHE_HIT_RATE:N/A"
fi
# 当前活跃查询数
ACTIVE_QUERIES=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW PROCESSLIST;" 2>/dev/null | grep -v "Sleep" | grep -v "binlog" | wc -l)
echo "ACTIVE_QUERIES:$ACTIVE_QUERIES"
# Binlog状态
BINLOG_STATUS=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW VARIABLES LIKE 'log_bin';" 2>/dev/null | awk '{print $2}')
if [ "$BINLOG_STATUS" = "ON" ]; then
BINLOG_COUNT=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW BINARY LOGS;" 2>/dev/null | wc -l)
echo "BINLOG_STATUS:ON/$BINLOG_COUNT"
else
echo "BINLOG_STATUS:OFF"
fi
# 表碎片检测 (DATA_FREE > 10MB的表数量)
FRAGMENTED_TABLES=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema','performance_schema','mysql','sys') AND DATA_FREE > 10485760;" 2>/dev/null)
if [ -n "$FRAGMENTED_TABLES" ] && [[ "$FRAGMENTED_TABLES" =~ ^[0-9]+$ ]]; then
echo "FRAGMENTED_TABLES:$FRAGMENTED_TABLES"
else
echo "FRAGMENTED_TABLES:0"
fi
# 连接错误统计
CONN_ERRORS=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW STATUS LIKE 'Aborted_connects';" 2>/dev/null | awk '{print $2}')
if [ -n "$CONN_ERRORS" ]; then
echo "CONN_ERRORS:$CONN_ERRORS"
else
echo "CONN_ERRORS:0"
fi
# InnoDB缓冲池大小
INNODB_BP_SIZE=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';" 2>/dev/null | awk '{print $2}')
if [ -n "$INNODB_BP_SIZE" ] && [ "$INNODB_BP_SIZE" -gt 0 ]; then
# 转换为MB
BP_SIZE_MB=$((INNODB_BP_SIZE / 1024 / 1024))
echo "INNODB_BP_SIZE:${BP_SIZE_MB}MB"
else
echo "INNODB_BP_SIZE:N/A"
fi
# 事务状态统计
TRX_ACTIVE=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW STATUS LIKE 'Innodb_trx_active';" 2>/dev/null | awk '{print $2}')
if [ -n "$TRX_ACTIVE" ]; then
echo "TRX_ACTIVE:$TRX_ACTIVE"
else
echo "TRX_ACTIVE:0"
fi
# 锁等待检测
LOCK_WAITS=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW STATUS LIKE 'Innodb_row_lock_current_waits';" 2>/dev/null | awk '{print $2}')
if [ -n "$LOCK_WAITS" ]; then
echo "LOCK_WAITS:$LOCK_WAITS"
else
echo "LOCK_WAITS:0"
fi
# 连接池分析(Threads_running/Threads_connected)
THREADS_RUNNING=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW STATUS LIKE 'Threads_running';" 2>/dev/null | awk '{print $2}')
THREADS_CONNECTED_NEW=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW STATUS LIKE 'Threads_connected';" 2>/dev/null | awk '{print $2}')
if [ -n "$THREADS_RUNNING" ] && [ -n "$THREADS_CONNECTED_NEW" ] && [ "$THREADS_CONNECTED_NEW" -gt 0 ]; then
IDLE_CONN=$((THREADS_CONNECTED_NEW - THREADS_RUNNING))
echo "THREADS_POOL:$THREADS_RUNNING/$THREADS_CONNECTED_NEW/$IDLE_CONN"
else
echo "THREADS_POOL:N/A"
fi
# InnoDB状态摘要
INNODB_STATUS=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW ENGINE INNODB STATUS\G" 2>/dev/null | grep -E "LATEST DETECTED DEADLOCK|TRANSACTIONS" | wc -l)
echo "INNODB_STATUS:$INNODB_STATUS"
# 临时表使用率
TEMP_TABLES=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW STATUS LIKE 'Created_tmp_disk_tables';" 2>/dev/null | awk '{print $2}')
TEMP_TABLES_TOTAL=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW STATUS LIKE 'Created_tmp_tables';" 2>/dev/null | awk '{print $2}')
if [ -n "$TEMP_TABLES" ] && [ -n "$TEMP_TABLES_TOTAL" ] && [ "$TEMP_TABLES_TOTAL" -gt 0 ]; then
TEMP_RATE=$(awk "BEGIN {printf \"%.2f\", ($TEMP_TABLES * 100) / $TEMP_TABLES_TOTAL}")
echo "TEMP_TABLE_RATE:$TEMP_RATE"
else
echo "TEMP_TABLE_RATE:N/A"
fi
# 数据库总大小(MB)
DB_SIZE=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema','performance_schema','mysql','sys');" 2>/dev/null)
if [ -n "$DB_SIZE" ]; then
echo "DATABASE_SIZE:${DB_SIZE}MB"
else
echo "DATABASE_SIZE:N/A"
fi
# 表数量统计
TABLE_COUNT=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema','performance_schema','mysql','sys') AND TABLE_TYPE='BASE TABLE';" 2>/dev/null)
if [ -n "$TABLE_COUNT" ]; then
echo "TABLE_COUNT:$TABLE_COUNT"
else
echo "TABLE_COUNT:0"
fi
# 复制状态
SLAVE_STATUS=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW SLAVE STATUS\G" 2>/dev/null | grep "Slave_IO_Running:" | awk '{print $2}')
if [ "$SLAVE_STATUS" = "Yes" ]; then
echo "REPLICATION_STATUS:SLAVE"
else
echo "REPLICATION_STATUS:MASTER"
fi
# Binlog过期时间(天)
BINLOG_EXPIRE=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW VARIABLES LIKE 'expire_logs_days';" 2>/dev/null | awk '{print $2}')
if [ -n "$BINLOG_EXPIRE" ]; then
echo "BINLOG_EXPIRE:${BINLOG_EXPIRE}days"
else
echo "BINLOG_EXPIRE:N/A"
fi
# ========== 高优先级功能补充 ==========
# 当前活跃查询详情 (SHOW PROCESSLIST)
PROCESSLIST_OUTPUT=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -e "SHOW PROCESSLIST;" 2>/dev/null | grep -v "Command" | head -10)
if [ -n "$PROCESSLIST_OUTPUT" ]; then
# 统计各状态查询数量
SLEEP_COUNT=$(echo "$PROCESSLIST_OUTPUT" | grep -c "Sleep" || echo "0")
QUERY_COUNT=$(echo "$PROCESSLIST_OUTPUT" | grep -v "Sleep" | wc -l)
LONG_QUERY_COUNT=$(echo "$PROCESSLIST_OUTPUT" | awk -F'\t' '{if ($6>5) print}' | wc -l)
echo "ACTIVE_PROCESSLIST:Sleep:${SLEEP_COUNT},Active:${QUERY_COUNT},LongRunning:${LONG_QUERY_COUNT}"
# 输出TOP5耗时查询
LONG_QUERIES=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -e "SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, LEFT(INFO, 50) AS QUERY FROM information_schema.PROCESSLIST WHERE COMMAND != 'Sleep' AND TIME > 0 ORDER BY TIME DESC LIMIT 5;" 2>/dev/null | grep -v "QUERY")
if [ -n "$LONG_QUERIES" ]; then
echo "LONG_QUERIES_TOP5:$(echo "$LONG_QUERIES" | head -5 | tr '\n' '|' | sed 's/|$//')"
else
echo "LONG_QUERIES_TOP5:N/A"
fi
else
echo "ACTIVE_PROCESSLIST:N/A"
echo "LONG_QUERIES_TOP5:N/A"
fi
# 缺少索引的高耗时查询 (通过performance_schema)
SLOW_QUERY_STATS=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -e "
SELECT
COUNT_STAR as exec_count,
ROUND(SUM_TIMER_WAIT/1000000000, 2) as total_time_sec,
ROUND(AVG_TIMER_WAIT/1000000000, 2) as avg_time_sec,
ROUND(SUM_LOCK_TIME/1000000000, 2) as lock_time_sec,
digest_text as query_sample
FROM performance_schema.events_statements_summary_by_digest
WHERE digest_text IS NOT NULL
AND digest_text NOT LIKE '%performance_schema%'
AND COUNT_STAR > 10
AND SUM_TIMER_WAIT > 1000000000
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 10;
" 2>/dev/null | grep -v "query_sample")
if [ -n "$SLOW_QUERY_STATS" ]; then
# 输出TOP1耗时查询的统计
TOP_QUERY=$(echo "$SLOW_QUERY_STATS" | head -2 | tail -1)
if [ -n "$TOP_QUERY" ]; then
EXEC_COUNT=$(echo "$TOP_QUERY" | awk '{print $1}')
TOTAL_TIME=$(echo "$TOP_QUERY" | awk '{print $2}')
AVG_TIME=$(echo "$TOP_QUERY" | awk '{print $3}')
LOCK_TIME=$(echo "$TOP_QUERY" | awk '{print $4}')
echo "SLOW_QUERY_TOP1:Exec:${EXEC_COUNT},TotalTime:${TOTAL_TIME}s,AvgTime:${AVG_TIME}s,LockTime:${LOCK_TIME}s"
else
echo "SLOW_QUERY_TOP1:N/A"
fi
else
echo "SLOW_QUERY_TOP1:N/A"
fi
# 缺少索引的表检测
MISSING_INDEX_TABLES=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -e "
SELECT
t.table_schema,
t.table_name,
t.table_rows,
ROUND(t.data_length / 1024 / 1024, 2) as data_mb
FROM information_schema.TABLES t
WHERE t.table_schema NOT IN ('information_schema','performance_schema','mysql','sys')
AND NOT EXISTS (
SELECT 1 FROM information_schema.STATISTICS s
WHERE s.table_schema = t.table_schema
AND s.table_name = t.table_name
)
AND t.table_rows > 1000
ORDER BY t.data_length DESC
LIMIT 5;
" 2>/dev/null | grep -v "data_mb")
if [ -n "$MISSING_INDEX_TABLES" ]; then
MISSING_COUNT=$(echo "$MISSING_INDEX_TABLES" | wc -l)
echo "TABLES_WITHOUT_INDEX:$MISSING_COUNT"
else
echo "TABLES_WITHOUT_INDEX:0"
fi
# ========== 中优先级功能补充 ==========
# 数据库列表详细输出
DATABASE_LIST=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "
SELECT
table_schema,
ROUND(sum(data_length + index_length) / 1024 / 1024, 2) as size_mb
FROM information_schema.tables
WHERE table_schema NOT IN ('information_schema','performance_schema','mysql','sys')
GROUP BY table_schema
ORDER BY size_mb DESC
LIMIT 10;
" 2>&1 | grep -v "\[Warning\]")
if [ -n "$DATABASE_LIST" ]; then
DB_COUNT=$(echo "$DATABASE_LIST" | wc -l)
TOTAL_SIZE=$(echo "$DATABASE_LIST" | awk -F'\t' '{sum+=$2} END {printf "%.2f", sum}')
DB_NAMES=$(echo "$DATABASE_LIST" | awk -F'\t' '{print $1}' | tr '\n' ',' | sed 's/,$//')
echo "DATABASE_LIST:Count:${DB_COUNT},TotalSize:${TOTAL_SIZE}MB,Databases:${DB_NAMES}"
else
echo "DATABASE_LIST:N/A"
fi
# InnoDB状态详情 (事务历史)
INNODB_TRX_INFO=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "
SELECT
COUNT(*) as trx_count,
IFNULL(SUM(TIMESTAMPDIFF(SECOND, trx_started, NOW())), 0) as total_trx_time
FROM information_schema.INNODB_TRX;
" 2>/dev/null)
if [ -n "$INNODB_TRX_INFO" ]; then
TRX_COUNT=$(echo "$INNODB_TRX_INFO" | awk -F'\t' '{print $1}')
TOTAL_TRX_TIME=$(echo "$INNODB_TRX_INFO" | awk -F'\t' '{print $2}')
echo "INNODB_TRX_DETAIL:Count:${TRX_COUNT},TotalTime:${TOTAL_TRX_TIME}s"
else
echo "INNODB_TRX_DETAIL:Count:0,TotalTime:0s"
fi
# 表统计 (ubains库TOP20)
UBAINS_TOP_TABLES=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -e "
SELECT
table_name,
table_rows,
round(data_length / 1024 / 1024, 2) as data_mb,
round(index_length / 1024 / 1024, 2) as index_mb,
round((data_length + index_length) / 1024 / 1024, 2) as total_mb
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'ubains'
ORDER BY (data_length + index_length) DESC
LIMIT 20;
" 2>/dev/null | grep -v "total_mb")
if [ -n "$UBAINS_TOP_TABLES" ]; then
TABLE_COUNT=$(echo "$UBAINS_TOP_TABLES" | wc -l)
# 获取TOP1表的信息
TOP1_TABLE=$(echo "$UBAINS_TOP_TABLES" | head -2 | tail -1)
if [ -n "$TOP1_TABLE" ]; then
TOP1_NAME=$(echo "$TOP1_TABLE" | awk '{print $1}')
TOP1_SIZE=$(echo "$TOP1_TABLE" | awk '{print $5}')
echo "UBAINS_TABLES_TOP20:Count:${TABLE_COUNT},Top1:${TOP1_NAME}:${TOP1_SIZE}MB"
else
echo "UBAINS_TABLES_TOP20:Count:${TABLE_COUNT}"
fi
else
echo "UBAINS_TABLES_TOP20:N/A"
fi
# 复制状态详情
SLAVE_STATUS_DETAIL=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -e "SHOW SLAVE STATUS\G" 2>/dev/null)
if [ -n "$SLAVE_STATUS_DETAIL" ]; then
# 提取关键复制状态信息
SLAVE_IO=$(echo "$SLAVE_STATUS_DETAIL" | grep "Slave_IO_Running:" | awk '{print $2}')
SLAVE_SQL=$(echo "$SLAVE_STATUS_DETAIL" | grep "Slave_SQL_Running:" | awk '{print $2}')
BEHIND_MASTER=$(echo "$SLAVE_STATUS_DETAIL" | grep "Seconds_Behind_Master:" | awk '{print $2}')
if [ "$SLAVE_IO" = "Yes" ]; then
echo "REPLICATION_DETAIL:IO:$SLAVE_IO,SQL:$SLAVE_SQL,Delay:${BEHIND_MASTER}s"
else
echo "REPLICATION_DETAIL:MASTER"
fi
else
echo "REPLICATION_DETAIL:MASTER"
fi
# 连接错误详细统计 - 该功能依赖的表在当前MySQL版本中不存在,已移除
# 使用基础的Aborted_connects统计即可(CONN_ERRORS变量)
# ========== 补充:InnoDB缓冲池详情 ==========
INNODB_BP_DETAIL=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -e "SHOW ENGINE INNODB STATUS\G" 2>/dev/null | grep -A 20 "Buffer pool hit rate")
if [ -n "$INNODB_BP_DETAIL" ]; then
BP_HIT_RATE=$(echo "$INNODB_BP_DETAIL" | grep -oP 'hit rate \K[\d/]+' | head -1)
if [ -n "$BP_HIT_RATE" ]; then
echo "INNODB_BP_DETAIL:HitRate:${BP_HIT_RATE}"
else
echo "INNODB_BP_DETAIL:N/A"
fi
else
echo "INNODB_BP_DETAIL:N/A"
fi
# ========== 补充:锁信息详情 ==========
LOCK_INFO=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "
SELECT
COUNT(*) as lock_waits,
IFNULL(SUM(TIMESTAMPDIFF(SECOND, r.trx_started, NOW())), 0) as total_wait_time
FROM information_schema.INNODB_LOCK_WAITS w
JOIN information_schema.INNODB_TRX r ON r.trx_id = w.requesting_trx_id;
" 2>/dev/null)
if [ -n "$LOCK_INFO" ]; then
LOCK_COUNT=$(echo "$LOCK_INFO" | awk -F'\t' '{print $1}')
WAIT_TIME=$(echo "$LOCK_INFO" | awk -F'\t' '{print $2}')
echo "LOCK_DETAIL:Waits:${LOCK_COUNT},TotalWait:${WAIT_TIME}s"
else
echo "LOCK_DETAIL:Waits:0,TotalWait:0s"
fi
# ========== 补充:表碎片检测详情 ==========
FRAGMENTED_TABLES_DETAIL=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "
SELECT
CONCAT(table_schema, '.', table_name) as table_name,
ROUND(data_length / 1024 / 1024, 2) as data_mb,
ROUND(data_free / 1024 / 1024, 2) as fragment_mb
FROM information_schema.TABLES
WHERE TABLE_SCHEMA NOT IN ('information_schema','performance_schema','mysql','sys')
AND DATA_FREE > 10485760
ORDER BY data_free DESC
LIMIT 5;
" 2>/dev/null | grep -v "fragment_mb")
if [ -n "$FRAGMENTED_TABLES_DETAIL" ]; then
FRAG_COUNT=$(echo "$FRAGMENTED_TABLES_DETAIL" | wc -l)
TOP_FRAG=$(echo "$FRAGMENTED_TABLES_DETAIL" | head -1)
if [ -n "$TOP_FRAG" ]; then
TABLE_NAME=$(echo "$TOP_FRAG" | awk '{print $1}')
FRAG_MB=$(echo "$TOP_FRAG" | awk '{print $3}')
echo "FRAGMENTED_DETAIL:Count:${FRAG_COUNT},Top1:${TABLE_NAME}:${FRAG_MB}MB"
else
echo "FRAGMENTED_DETAIL:Count:${FRAG_COUNT}"
fi
else
echo "FRAGMENTED_DETAIL:Count:0"
fi
#!/bin/bash
# Redis深度检测脚本
# 使用方法: ./redis_depth_check.sh
REDIS_PASSWORD="dNrprU&2S"
CONTAINER="uredis"
# 基础信息
REDIS_VERSION=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" INFO server 2>&1 | grep redis_version | cut -d: -f2 | tr -d '\r')
if [ -n "$REDIS_VERSION" ]; then
echo "REDIS_VERSION:$REDIS_VERSION"
else
echo "REDIS_VERSION:N/A"
fi
# 运行时间(天)
UPTIME_DAYS=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" INFO server 2>&1 | grep uptime_in_days | cut -d: -f2 | tr -d '\r')
if [ -n "$UPTIME_DAYS" ]; then
echo "UPTIME_DAYS:$UPTIME_DAYS"
else
echo "UPTIME_DAYS:N/A"
fi
# 键数量
KEY_COUNT=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" DBSIZE 2>&1 | grep -v "Warning")
if [ -n "$KEY_COUNT" ] && [[ "$KEY_COUNT" =~ ^[0-9]+$ ]]; then
echo "KEY_COUNT:$KEY_COUNT"
else
echo "KEY_COUNT:0"
fi
# 内存使用
MEMORY_INFO=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" INFO memory 2>&1 | grep -E "used_memory_human:|mem_fragmentation_ratio:" | tr -d '\r' | tr '\n' '|' | sed 's/|$//')
if [ -n "$MEMORY_INFO" ]; then
echo "MEMORY_INFO:$MEMORY_INFO"
else
echo "MEMORY_INFO:N/A"
fi
# 客户端连接数
CLIENT_COUNT=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" INFO clients 2>&1 | grep connected_clients | cut -d: -f2 | tr -d '\r')
if [ -n "$CLIENT_COUNT" ]; then
echo "CLIENT_COUNT:$CLIENT_COUNT"
else
echo "CLIENT_COUNT:0"
fi
# ========== 高优先级功能补充 ==========
# Keyspace信息(各数据库键和过期键统计)
KEYSPACE_INFO=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" INFO keyspace 2>&1 | grep -v "Warning" | grep "^db" | tr -d '\r')
if [ -n "$KEYSPACE_INFO" ]; then
TOTAL_KEYS=0
TOTAL_EXPIRES=0
while IFS=: read -r db_key info; do
if [[ "$info" =~ keys=([0-9]+) ]]; then
keys=${BASH_REMATCH[1]}
TOTAL_KEYS=$((TOTAL_KEYS + keys))
fi
if [[ "$info" =~ expires=([0-9]+) ]]; then
expires=${BASH_REMATCH[1]}
TOTAL_EXPIRES=$((TOTAL_EXPIRES + expires))
fi
done <<< "$KEYSPACE_INFO"
echo "KEYSPACE_DETAIL:Total:$TOTAL_KEYS,Expires:$TOTAL_EXPIRES"
else
echo "KEYSPACE_DETAIL:N/A"
fi
# 键类型分布采样(采样前100个键)
KEY_TYPE_SAMPLE=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" --scan --count 100 2>&1 | head -100 | xargs -I {} docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" TYPE {} 2>&1 | grep -v "Warning" | sort | uniq -c | awk '{print $2":"$1}' | tr '\n' '|' | sed 's/|$//' | sed 's/ /:/g')
if [ -n "$KEY_TYPE_SAMPLE" ]; then
echo "KEY_TYPE_DISTRIBUTION:$KEY_TYPE_SAMPLE"
else
echo "KEY_TYPE_DISTRIBUTION:N/A"
fi
# ========== 中优先级功能补充 ==========
# 持久化信息
PERSISTENCE_INFO=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" INFO persistence 2>&1 | grep -v "Warning" | grep -E "rdb_last_cow_size:|aof_enabled:|rdb_last_save_time:" | tr -d '\r' | tr '\n' '|' | sed 's/|$//')
if [ -n "$PERSISTENCE_INFO" ]; then
# 解析持久化状态
RDB_COW=$(echo "$PERSISTENCE_INFO" | grep -oP 'rdb_last_cow_size:\K\d+' | head -1)
AOF_ENABLED=$(echo "$PERSISTENCE_INFO" | grep -oP 'aof_enabled:\K\d+' | head -1)
RDB_STATUS="空闲"
if [ "$RDB_COW" -gt 0 ] 2>/dev/null; then
RDB_STATUS="备份中"
fi
AOF_STATUS="未启用"
if [ "$AOF_ENABLED" = "1" ]; then
AOF_STATUS="已启用"
fi
echo "PERSISTENCE_STATUS:RDB:$RDB_STATUS,AOF:$AOF_STATUS"
else
echo "PERSISTENCE_STATUS:N/A"
fi
# 复制信息
REPL_INFO=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" INFO replication 2>&1 | grep -v "Warning" | grep -E "role:|connected_slaves:|master_link_status:" | tr -d '\r' | tr '\n' '|' | sed 's/|$//')
if [ -n "$REPL_INFO" ]; then
ROLE=$(echo "$REPL_INFO" | grep -oP 'role:\K\w+' | head -1)
CONNECTED_SLAVES=$(echo "$REPL_INFO" | grep -oP 'connected_slaves:\K\d+' | head -1)
MASTER_LINK=$(echo "$REPL_INFO" | grep -oP 'master_link_status:\K\w+' | head -1)
if [ "$ROLE" = "master" ]; then
echo "REPLICATION_STATUS:Role:$ROLE,Slaves:${CONNECTED_SLAVES:-0}"
elif [ "$ROLE" = "slave" ]; then
echo "REPLICATION_STATUS:Role:$ROLE,MasterLink:${MASTER_LINK:-unknown}"
else
echo "REPLICATION_STATUS:Role:$ROLE"
fi
else
echo "REPLICATION_STATUS:N/A"
fi
# 慢日志TOP10
SLOW_LOG=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" SLOWLOG GET 10 2>&1 | grep -v "Warning" | head -40)
if [ -n "$SLOW_LOG" ]; then
# SLOWLOG输出格式:每4行一个记录 (ID, timestamp, duration, command)
# 我们需要获取所有记录的第3行(持续时间)
SLOW_COUNT=0
SLOWEST_TIME=0
line_num=0
while IFS= read -r line; do
line_num=$((line_num + 1))
# 每第3行是持续时间
if [ $((line_num % 4)) -eq 3 ]; then
if [[ "$line" =~ ^[0-9]+$ ]]; then
duration=$line
if [ $duration -gt $SLOWEST_TIME ]; then
SLOWEST_TIME=$duration
fi
SLOW_COUNT=$((SLOW_COUNT + 1))
fi
fi
done <<< "$SLOW_LOG"
if [ $SLOW_COUNT -gt 0 ]; then
echo "SLOW_LOG_TOP10:Count:$SLOW_COUNT,Slowest:${SLOWEST_TIME}us"
else
echo "SLOW_LOG_TOP10:Count:0"
fi
else
echo "SLOW_LOG_TOP10:Count:0"
fi
# 命令统计TOP5
CMD_STATS=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" INFO commandstats 2>&1 | grep -v "Warning" | grep "cmdstat_" | tr -d '\r')
if [ -n "$CMD_STATS" ]; then
# 提取命令调用次数TOP5
TOP_COMMANDS=$(echo "$CMD_STATS" | grep -oP 'cmdstat_\K[a-z]+(?=:calls=\d+)' | head -5 | tr '\n' ',' | sed 's/,$//')
TOP_CALLS=$(echo "$CMD_STATS" | grep -oP 'cmdstat_[a-z]+:calls=\K\d+' | head -5 | tr '\n' ',' | sed 's/,$//')
if [ -n "$TOP_COMMANDS" ]; then
# 组合命令和调用次数
CMD_DETAIL=""
IFS=',' read -ra CMDS <<< "$TOP_COMMANDS"
IFS=',' read -ra CALLS <<< "$TOP_CALLS"
for i in "${!CMDS[@]}"; do
if [ -n "$CMD_DETAIL" ]; then
CMD_DETAIL="$CMD_DETAIL,"
fi
CMD_DETAIL="$CMD_DETAIL${CMDS[$i]}:${CALLS[$i]}"
done
echo "COMMAND_STATS_TOP5:$CMD_DETAIL"
else
echo "COMMAND_STATS_TOP5:N/A"
fi
else
echo "COMMAND_STATS_TOP5:N/A"
fi
# 客户端列表摘要
CLIENT_LIST=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" CLIENT LIST 2>&1 | grep -v "Warning" | grep "id=" | tr -d '\r')
if [ -n "$CLIENT_LIST" ]; then
TOTAL_CLIENTS=$(echo "$CLIENT_LIST" | wc -l)
IDLE_CLIENTS=0
BLOCKING_CLIENTS=0
while IFS='=' read -r key value; do
if [[ "$value" =~ idle=([0-9]+) ]]; then
idle_time=${BASH_REMATCH[1]}
if [ "$idle_time" -gt 300 ]; then
IDLE_CLIENTS=$((IDLE_CLIENTS + 1))
fi
fi
if [[ "$value" =~ blocking=1 ]]; then
BLOCKING_CLIENTS=$((BLOCKING_CLIENTS + 1))
fi
done <<< "$CLIENT_LIST"
echo "CLIENT_DETAIL:Total:$TOTAL_CLIENTS,IdleOver5min:$IDLE_CLIENTS,Blocking:$BLOCKING_CLIENTS"
else
echo "CLIENT_DETAIL:N/A"
fi
# 缓存命中率
STATS_INFO=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" INFO stats 2>&1 | grep -v "Warning" | grep -E "keyspace_hits:|keyspace_misses:|rejected_connections:" | tr -d '\r')
if [ -n "$STATS_INFO" ]; then
HITS=$(echo "$STATS_INFO" | grep keyspace_hits | cut -d: -f2)
MISSES=$(echo "$STATS_INFO" | grep keyspace_misses | cut -d: -f2)
REJECTED=$(echo "$STATS_INFO" | grep rejected_connections | cut -d: -f2)
if [ -n "$HITS" ] && [ -n "$MISSES" ]; then
TOTAL_REQ=$((HITS + MISSES))
if [ "$TOTAL_REQ" -gt 0 ]; then
HIT_RATE=$(awk "BEGIN {printf \"%.2f\", ($HITS * 100) / $TOTAL_REQ}")
else
HIT_RATE="0.00"
fi
echo "CACHE_HIT_RATE:Hits:$HITS,Misses:$MISSES,Rate:$HIT_RATE%"
else
echo "CACHE_HIT_RATE:N/A"
fi
if [ -n "$REJECTED" ]; then
echo "REJECTED_CONNECTIONS:$REJECTED"
fi
else
echo "CACHE_HIT_RATE:N/A"
echo "REJECTED_CONNECTIONS:0"
fi
# 配置检查
CONFIG_MAXCLIENTS=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" CONFIG GET maxclients 2>&1 | grep -v "Warning" | tail -1 | tr -d '\r')
CONFIG_TIMEOUT=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" CONFIG GET timeout 2>&1 | grep -v "Warning" | tail -1 | tr -d '\r')
CONFIG_SAVE=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" CONFIG GET save 2>&1 | grep -v "Warning" | tail -1 | tr -d '\r')
echo "CONFIG_CHECK:MaxClients:$CONFIG_MAXCLIENTS,Timeout:${CONFIG_TIMEOUT}s,Save:$CONFIG_SAVE"
# ========== 补充:集群状态检测 ==========
CLUSTER_INFO=$(docker exec $CONTAINER redis-cli -a "$REDIS_PASSWORD" CLUSTER INFO 2>&1 | grep -v "Warning")
if [ -n "$CLUSTER_INFO" ]; then
# 解析集群状态
CLUSTER_STATE=$(echo "$CLUSTER_INFO" | grep -oP 'cluster_state:\K\w+' | head -1)
CLUSTER_SLOTS_ASSIGNED=$(echo "$CLUSTER_INFO" | grep -oP 'cluster_slots_assigned:\K\d+' | head -1)
CLUSTER_SLOTS_OK=$(echo "$CLUSTER_INFO" | grep -oP 'cluster_slots_ok:\K\d+' | head -1)
CLUSTER_KNOWN_NODES=$(echo "$CLUSTER_INFO" | grep -oP 'cluster_known_nodes:\K\d+' | head -1)
if [ "$CLUSTER_STATE" = "ok" ]; then
echo "CLUSTER_STATUS:State:OK,Nodes:${CLUSTER_KNOWN_NODES:-1},Slots:${CLUSTER_SLOTS_ASSIGNED:-0}/${CLUSTER_SLOTS_OK:-0}"
else
echo "CLUSTER_STATUS:State:${CLUSTER_STATE},Nodes:${CLUSTER_KNOWN_NODES:-1}"
fi
else
# 非集群模式,检测单机状态
echo "CLUSTER_STATUS:Standalone"
fi
#!/bin/bash
################################################################################
# UStorage容器监测模块
# 功能: 检测ustorage容器运行状态、健康检查、存储容量与IO
# 作者: 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_container_status() {
local container_name
container_name=$(resolve_container ustorge 2>/dev/null)
if [ -z "$container_name" ]; then
# 尝试其他可能的名称
container_name=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE "ustorage|storage" | head -1)
fi
if [ -z "$container_name" ]; then
output_result "USTORAGE_CONTAINER_STATUS" "未运行"
output_result "USTORAGE_CONTAINER_LEVEL" "严重"
return 1
fi
output_result "USTORAGE_CONTAINER_NAME" "$container_name"
# 检查容器状态
local status
status=$(docker inspect --format='{{.State.Status}}' "$container_name" 2>/dev/null)
if [ "$status" = "running" ]; then
output_result "USTORAGE_CONTAINER_STATUS" "运行中"
output_result "USTORAGE_CONTAINER_LEVEL" "正常"
else
output_result "USTORAGE_CONTAINER_STATUS" "$status"
output_result "USTORAGE_CONTAINER_LEVEL" "严重"
return 1
fi
# 重启次数
local restart_count
restart_count=$(docker inspect --format='{{.RestartCount}}' "$container_name" 2>/dev/null)
output_result "USTORAGE_RESTART_COUNT" "${restart_count:-0}"
if [ "${restart_count:-0}" -gt 3 ]; then
output_result "USTORAGE_RESTART_LEVEL" "警告"
else
output_result "USTORAGE_RESTART_LEVEL" "正常"
fi
# 运行时长(秒)
local start_time
start_time=$(docker inspect --format='{{.State.StartedAt}}' "$container_name" 2>/dev/null)
if [ -n "$start_time" ]; then
local start_epoch uptime_seconds
start_epoch=$(date -d "$start_time" +%s 2>/dev/null || echo "0")
if [ "$start_epoch" -gt 0 ]; then
uptime_seconds=$(( $(date +%s) - start_epoch ))
output_result "USTORAGE_UPTIME_SECONDS" "$uptime_seconds"
fi
fi
return 0
}
# 检测容器资源使用
check_container_resources() {
local container_name
container_name=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE "ustorage|storage" | head -1)
if [ -z "$container_name" ]; then
return 1
fi
# CPU使用率
local cpu_percent
cpu_percent=$(docker stats --no-stream --format '{{.CPUPerc}}' "$container_name" 2>/dev/null | tr -d '%')
if [ -n "$cpu_percent" ]; then
output_result "USTORAGE_CPU_USAGE" "$cpu_percent"
fi
# 内存使用
local mem_usage mem_limit mem_percent
mem_usage=$(docker stats --no-stream --format '{{.MemUsage}}' "$container_name" 2>/dev/null)
if [ -n "$mem_usage" ]; then
output_result "USTORAGE_MEMORY_USAGE" "$mem_usage"
fi
mem_percent=$(docker stats --no-stream --format '{{.MemPerc}}' "$container_name" 2>/dev/null | tr -d '%')
if [ -n "$mem_percent" ]; then
output_result "USTORAGE_MEMORY_PERCENT" "$mem_percent"
fi
# 网络IO
local net_io
net_io=$(docker stats --no-stream --format '{{.NetIO}}' "$container_name" 2>/dev/null)
if [ -n "$net_io" ]; then
output_result "USTORAGE_NET_IO" "$net_io"
fi
# 磁盘IO
local block_io
block_io=$(docker stats --no-stream --format '{{.BlockIO}}' "$container_name" 2>/dev/null)
if [ -n "$block_io" ]; then
output_result "USTORAGE_BLOCK_IO" "$block_io"
fi
}
# 检测服务健康状态(HTTP健康检查)
check_health_endpoint() {
local container_name
container_name=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE "ustorage|storage" | head -1)
if [ -z "$container_name" ]; then
return 1
fi
# 获取容器IP
local container_ip
container_ip=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$container_name" 2>/dev/null)
if [ -z "$container_ip" ]; then
output_result "USTORAGE_HEALTH_CHECK" "无法获取IP"
return 1
fi
output_result "USTORAGE_CONTAINER_IP" "$container_ip"
# 尝试常见的健康检查端口
local ports="8080 80 9000 3000"
local health_ok=false
local response_time
for port in $ports; do
# 检查端口是否监听
if timeout 5 bash -c "echo >/dev/tcp/$container_ip/$port" 2>/dev/null; then
output_result "USTORAGE_SERVICE_PORT" "$port"
# 尝试健康检查接口
local start_time end_time
start_time=$(date +%s%N 2>/dev/null || echo "0")
if curl -sf "http://$container_ip:$port/health" -o /dev/null --connect-timeout 5 --max-time 10 2>/dev/null; then
health_ok=true
end_time=$(date +%s%N 2>/dev/null || echo "0")
response_time=$(( (end_time - start_time) / 1000000 ))
output_result "USTORAGE_HEALTH_CHECK" "正常"
output_result "USTORAGE_RESPONSE_TIME" "${response_time}ms"
output_result "USTORAGE_HEALTH_LEVEL" "正常"
break
elif curl -sf "http://$container_ip:$port/" -o /dev/null --connect-timeout 5 --max-time 10 2>/dev/null; then
health_ok=true
end_time=$(date +%s%N 2>/dev/null || echo "0")
response_time=$(( (end_time - start_time) / 1000000 ))
output_result "USTORAGE_HEALTH_CHECK" "正常"
output_result "USTORAGE_RESPONSE_TIME" "${response_time}ms"
output_result "USTORAGE_HEALTH_LEVEL" "正常"
break
fi
fi
done
if [ "$health_ok" = false ]; then
output_result "USTORAGE_HEALTH_CHECK" "无法访问"
output_result "USTORAGE_HEALTH_LEVEL" "警告"
fi
}
# 检测存储容量(通过容器内命令)
check_storage_capacity() {
local container_name
container_name=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE "ustorage|storage" | head -1)
if [ -z "$container_name" ]; then
return 1
fi
# 检查容器内数据目录大小
local data_dirs="/data /storage /var/lib/storage"
for dir in $data_dirs; do
# 尝试在容器内执行命令
local dir_size
dir_size=$(docker exec "$container_name" du -sh "$dir" 2>/dev/null | awk '{print $1}')
if [ -n "$dir_size" ]; then
output_result "USTORAGE_DATA_SIZE" "$dir_size"
break
fi
done
# 检查磁盘使用率(容器视角)
local disk_usage
disk_usage=$(docker exec "$container_name" df -h / 2>/dev/null | awk 'NR==2 {print $5}' | tr -d '%')
if [ -n "$disk_usage" ]; then
output_result "USTORAGE_DISK_USAGE" "$disk_usage"
if [ "$disk_usage" -gt 90 ]; then
output_result "USTORAGE_DISK_LEVEL" "严重"
elif [ "$disk_usage" -gt 80 ]; then
output_result "USTORAGE_DISK_LEVEL" "警告"
else
output_result "USTORAGE_DISK_LEVEL" "正常"
fi
fi
# 检查inode使用率
local inode_usage
inode_usage=$(docker exec "$container_name" df -i / 2>/dev/null | awk 'NR==2 {print $5}' | tr -d '%')
if [ -n "$inode_usage" ]; then
output_result "USTORAGE_INODE_USAGE" "$inode_usage"
fi
}
# 检测日志大小
check_log_size() {
local container_name
container_name=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE "ustorage|storage" | head -1)
if [ -z "$container_name" ]; then
return 1
fi
# 检查容器日志文件大小
local log_path
log_path=$(docker inspect --format='{{.LogPath}}' "$container_name" 2>/dev/null)
if [ -n "$log_path" ] && [ -f "$log_path" ]; then
local log_size
log_size=$(du -sh "$log_path" 2>/dev/null | awk '{print $1}')
if [ -n "$log_size" ]; then
output_result "USTORAGE_LOG_SIZE" "$log_size"
# 检查是否超过500MB
local log_bytes
log_bytes=$(stat -c%s "$log_path" 2>/dev/null || echo "0")
if [ "$log_bytes" -gt 524288000 ]; then
output_result "USTORAGE_LOG_LEVEL" "警告"
else
output_result "USTORAGE_LOG_LEVEL" "正常"
fi
fi
fi
}
# ==================== 主检测流程 ====================
main() {
log_info "开始UStorage容器监测..."
# 执行各项检测
check_container_status && {
check_container_resources
check_health_endpoint
check_storage_capacity
check_log_size
}
log_info "UStorage容器监测完成"
}
# 执行主函数
main
\ No newline at end of file
#!/bin/bash
################################################################################
# UTracker容器监测模块
# 功能: 检测utracker容器运行状态、健康检查、处理能力与队列状态
# 作者: 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_container_status() {
local container_name
container_name=$(resolve_container utracker 2>/dev/null)
if [ -z "$container_name" ]; then
container_name=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE "utracker|tracker" | head -1)
fi
if [ -z "$container_name" ]; then
output_result "UTRACKER_CONTAINER_STATUS" "未运行"
output_result "UTRACKER_CONTAINER_LEVEL" "严重"
return 1
fi
output_result "UTRACKER_CONTAINER_NAME" "$container_name"
# 检查容器状态
local status
status=$(docker inspect --format='{{.State.Status}}' "$container_name" 2>/dev/null)
if [ "$status" = "running" ]; then
output_result "UTRACKER_CONTAINER_STATUS" "运行中"
output_result "UTRACKER_CONTAINER_LEVEL" "正常"
else
output_result "UTRACKER_CONTAINER_STATUS" "$status"
output_result "UTRACKER_CONTAINER_LEVEL" "严重"
return 1
fi
# 重启次数
local restart_count
restart_count=$(docker inspect --format='{{.RestartCount}}' "$container_name" 2>/dev/null)
output_result "UTRACKER_RESTART_COUNT" "${restart_count:-0}"
if [ "${restart_count:-0}" -gt 3 ]; then
output_result "UTRACKER_RESTART_LEVEL" "警告"
else
output_result "UTRACKER_RESTART_LEVEL" "正常"
fi
# 运行时长(秒)
local start_time
start_time=$(docker inspect --format='{{.State.StartedAt}}' "$container_name" 2>/dev/null)
if [ -n "$start_time" ]; then
local start_epoch uptime_seconds
start_epoch=$(date -d "$start_time" +%s 2>/dev/null || echo "0")
if [ "$start_epoch" -gt 0 ]; then
uptime_seconds=$(( $(date +%s) - start_epoch ))
output_result "UTRACKER_UPTIME_SECONDS" "$uptime_seconds"
fi
fi
return 0
}
# 检测容器资源使用
check_container_resources() {
local container_name
container_name=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE "utracker|tracker" | head -1)
if [ -z "$container_name" ]; then
return 1
fi
# CPU使用率
local cpu_percent
cpu_percent=$(docker stats --no-stream --format '{{.CPUPerc}}' "$container_name" 2>/dev/null | tr -d '%')
if [ -n "$cpu_percent" ]; then
output_result "UTRACKER_CPU_USAGE" "$cpu_percent"
fi
# 内存使用
local mem_usage mem_percent
mem_usage=$(docker stats --no-stream --format '{{.MemUsage}}' "$container_name" 2>/dev/null)
if [ -n "$mem_usage" ]; then
output_result "UTRACKER_MEMORY_USAGE" "$mem_usage"
fi
mem_percent=$(docker stats --no-stream --format '{{.MemPerc}}' "$container_name" 2>/dev/null | tr -d '%')
if [ -n "$mem_percent" ]; then
output_result "UTRACKER_MEMORY_PERCENT" "$mem_percent"
fi
# 网络IO
local net_io
net_io=$(docker stats --no-stream --format '{{.NetIO}}' "$container_name" 2>/dev/null)
if [ -n "$net_io" ]; then
output_result "UTRACKER_NET_IO" "$net_io"
fi
# 磁盘IO
local block_io
block_io=$(docker stats --no-stream --format '{{.BlockIO}}' "$container_name" 2>/dev/null)
if [ -n "$block_io" ]; then
output_result "UTRACKER_BLOCK_IO" "$block_io"
fi
}
# 检测服务健康状态
check_health_endpoint() {
local container_name
container_name=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE "utracker|tracker" | head -1)
if [ -z "$container_name" ]; then
return 1
fi
# 获取容器IP
local container_ip
container_ip=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$container_name" 2>/dev/null)
if [ -z "$container_ip" ]; then
output_result "UTRACKER_HEALTH_CHECK" "无法获取IP"
return 1
fi
output_result "UTRACKER_CONTAINER_IP" "$container_ip"
# 尝试常见的健康检查端口
local ports="8080 80 9000 3000 6969"
local health_ok=false
local response_time
for port in $ports; do
if timeout 5 bash -c "echo >/dev/tcp/$container_ip/$port" 2>/dev/null; then
output_result "UTRACKER_SERVICE_PORT" "$port"
local start_time end_time
start_time=$(date +%s%N 2>/dev/null || echo "0")
if curl -sf "http://$container_ip:$port/health" -o /dev/null --connect-timeout 5 --max-time 10 2>/dev/null; then
health_ok=true
end_time=$(date +%s%N 2>/dev/null || echo "0")
response_time=$(( (end_time - start_time) / 1000000 ))
output_result "UTRACKER_HEALTH_CHECK" "正常"
output_result "UTRACKER_RESPONSE_TIME" "${response_time}ms"
output_result "UTRACKER_HEALTH_LEVEL" "正常"
break
elif curl -sf "http://$container_ip:$port/" -o /dev/null --connect-timeout 5 --max-time 10 2>/dev/null; then
health_ok=true
end_time=$(date +%s%N 2>/dev/null || echo "0")
response_time=$(( (end_time - start_time) / 1000000 ))
output_result "UTRACKER_HEALTH_CHECK" "正常"
output_result "UTRACKER_RESPONSE_TIME" "${response_time}ms"
output_result "UTRACKER_HEALTH_LEVEL" "正常"
break
fi
fi
done
if [ "$health_ok" = false ]; then
output_result "UTRACKER_HEALTH_CHECK" "无法访问"
output_result "UTRACKER_HEALTH_LEVEL" "警告"
fi
}
# 检测Tracker处理能力
check_processing_capacity() {
local container_name
container_name=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE "utracker|tracker" | head -1)
if [ -z "$container_name" ]; then
return 1
fi
# 检查容器内进程数
local process_count
process_count=$(docker exec "$container_name" ps aux 2>/dev/null | wc -l)
if [ -n "$process_count" ]; then
output_result "UTRACKER_PROCESS_COUNT" "$((process_count - 1))"
fi
# 检查容器内线程数
local thread_count
thread_count=$(docker exec "$container_name" bash -c 'ls /proc/*/task 2>/dev/null | wc -l' 2>/dev/null)
if [ -n "$thread_count" ]; then
output_result "UTRACKER_THREAD_COUNT" "$thread_count"
fi
# 检查容器内打开的文件描述符
local fd_count
fd_count=$(docker exec "$container_name" bash -c 'ls /proc/*/fd 2>/dev/null | wc -l' 2>/dev/null)
if [ -n "$fd_count" ]; then
output_result "UTRACKER_FD_COUNT" "$fd_count"
fi
# 检查容器内TCP连接状态
local tcp_established tcp_time_wait tcp_close_wait
tcp_established=$(docker exec "$container_name" bash -c 'cat /proc/net/tcp 2>/dev/null | awk "{print \$4}" | grep -c "01" || echo 0' 2>/dev/null)
if [ -n "$tcp_established" ]; then
output_result "UTRACKER_TCP_ESTABLISHED" "$tcp_established"
fi
tcp_time_wait=$(docker exec "$container_name" bash -c 'cat /proc/net/tcp 2>/dev/null | awk "{print \$4}" | grep -c "06" || echo 0' 2>/dev/null)
if [ -n "$tcp_time_wait" ]; then
output_result "UTRACKER_TCP_TIME_WAIT" "$tcp_time_wait"
fi
tcp_close_wait=$(docker exec "$container_name" bash -c 'cat /proc/net/tcp 2>/dev/null | awk "{print \$4}" | grep -c "08" || echo 0' 2>/dev/null)
if [ -n "$tcp_close_wait" ]; then
output_result "UTRACKER_TCP_CLOSE_WAIT" "$tcp_close_wait"
if [ "$tcp_close_wait" -gt 50 ]; then
output_result "UTRACKER_TCP_LEVEL" "警告"
else
output_result "UTRACKER_TCP_LEVEL" "正常"
fi
fi
# 检查容器磁盘使用
local disk_usage
disk_usage=$(docker exec "$container_name" df -h / 2>/dev/null | awk 'NR==2 {print $5}' | tr -d '%')
if [ -n "$disk_usage" ]; then
output_result "UTRACKER_DISK_USAGE" "$disk_usage"
if [ "$disk_usage" -gt 90 ]; then
output_result "UTRACKER_DISK_LEVEL" "严重"
elif [ "$disk_usage" -gt 80 ]; then
output_result "UTRACKER_DISK_LEVEL" "警告"
else
output_result "UTRACKER_DISK_LEVEL" "正常"
fi
fi
}
# 检测日志大小
check_log_size() {
local container_name
container_name=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE "utracker|tracker" | head -1)
if [ -z "$container_name" ]; then
return 1
fi
# 检查容器日志文件大小
local log_path
log_path=$(docker inspect --format='{{.LogPath}}' "$container_name" 2>/dev/null)
if [ -n "$log_path" ] && [ -f "$log_path" ]; then
local log_size
log_size=$(du -sh "$log_path" 2>/dev/null | awk '{print $1}')
if [ -n "$log_size" ]; then
output_result "UTRACKER_LOG_SIZE" "$log_size"
local log_bytes
log_bytes=$(stat -c%s "$log_path" 2>/dev/null || echo "0")
if [ "$log_bytes" -gt 524288000 ]; then
output_result "UTRACKER_LOG_LEVEL" "警告"
else
output_result "UTRACKER_LOG_LEVEL" "正常"
fi
fi
fi
}
# ==================== 主检测流程 ====================
main() {
log_info "开始UTracker容器监测..."
# 执行各项检测
check_container_status && {
check_container_resources
check_health_endpoint
check_processing_capacity
check_log_size
}
log_info "UTracker容器监测完成"
}
# 执行主函数
main
\ No newline at end of file
#!/bin/bash
################################################################################
# OOM和内核异常检测模块
# 功能: 检测OOM Killer事件、Core dump文件、文件系统只读状态等内核异常
# 作者: 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
# ==================== 检测函数 ====================
# 检测OOM Killer事件
check_oom_killer() {
local oom_count=0
local oom_recent=0
local oom_output=""
# 从 dmesg 检查OOM记录
if command -v dmesg &> /dev/null; then
# 检查是否有OOM记录
oom_output=$(dmesg -T 2>/dev/null | grep -i "Out of memory\|Killed process" | tail -5)
oom_count=$(echo "$oom_output" | wc -l)
# 检查最近7天的OOM记录
oom_recent=$(dmesg -T 2>/dev/null | grep -i "Out of memory\|Killed process" | grep -E "$(date +%Y-%m-%d --date='7 days ago')|$(date +%Y-%m-%d --date='6 days ago')|$(date +%Y-%m-%d --date='5 days ago')|$(date +%Y-%m-%d --date='4 days ago')|$(date +%Y-%m-%d --date='3 days ago')|$(date +%Y-%m-%d --date='2 days ago')|$(date +%Y-%m-%d --date='1 days ago')|$(date +%Y-%m-%d)" | wc -l)
fi
# 从系统日志检查OOM记录
if [ -r /var/log/messages ]; then
local log_oom=$(grep -i "Out of memory\|Killed process" /var/log/messages 2>/dev/null | tail -5)
if [ -n "$log_oom" ]; then
oom_output="${oom_output}${log_oom}"
fi
elif [ -r /var/log/syslog ]; then
local log_oom=$(grep -i "Out of memory\|Killed process" /var/log/syslog 2>/dev/null | tail -5)
if [ -n "$log_oom" ]; then
oom_output="${oom_output}${log_oom}"
fi
fi
output_result "OOM_COUNT" "$oom_count"
output_result "OOM_RECENT_DAYS" "$oom_recent"
if [ "$oom_count" -gt 0 ]; then
output_result "OOM_STATUS" "严重"
echo "ERROR:检测到OOM Killer事件,系统可能内存不足"
else
output_result "OOM_STATUS" "正常"
fi
}
# 检测Core dump文件
check_core_dumps() {
local core_count=0
local core_files=""
# 在常见目录查找core文件
local search_dirs="/data /tmp /root /var/crash"
for dir in $search_dirs; do
if [ -d "$dir" ]; then
local found=$(find "$dir" -name "core.*" -mtime -7 2>/dev/null)
if [ -n "$found" ]; then
core_files="${core_files}${found}"$'\n'
fi
fi
done
core_count=$(echo "$core_files" | grep -c "core" || echo "0")
if [ "$core_count" -gt 0 ]; then
output_result "CORE_DUMP_COUNT" "$core_count"
output_result "CORE_DUMP_STATUS" "警告"
echo "ERROR:检测到${core_count}个core dump文件,可能有程序崩溃"
else
output_result "CORE_DUMP_COUNT" "0"
output_result "CORE_DUMP_STATUS" "正常"
fi
}
# 检测只读文件系统
check_readonly_fs() {
local ro_fs=0
# 检查 /proc/mounts 中是否有只读挂载的文件系统
ro_fs=$(cat /proc/mounts 2>/dev/null | grep -c 'ro,' || echo "0")
# 排除预期的只读文件系统(如squashfs、iso9660等)
local ro_expected=$(cat /proc/mounts 2>/dev/null | grep -E 'squashfs|iso9660|overlay' | wc -l)
ro_fs=$((ro_fs - ro_expected))
if [ "$ro_fs" -gt 0 ]; then
output_result "READONLY_FS_COUNT" "$ro_fs"
output_result "READONLY_FS_STATUS" "严重"
echo "ERROR:检测到只读文件系统,可能磁盘故障"
else
output_result "READONLY_FS_COUNT" "0"
output_result "READONLY_FS_STATUS" "正常"
fi
}
# 检测内核错误日志
check_kernel_errors() {
local kernel_errors=0
if command -v dmesg &> /dev/null; then
# 检查内核错误
kernel_errors=$(dmesg -T 2>/dev/null | grep -iE "error|failed|warning" | grep -v "ACPI" | wc -l)
fi
output_result "KERNEL_ERRORS" "$kernel_errors"
if [ "$kernel_errors" -gt 50 ]; then
output_result "KERNEL_STATUS" "警告"
else
output_result "KERNEL_STATUS" "正常"
fi
}
# 检测软锁定(Soft Lockup)
check_soft_lockup() {
local lockup_count=0
if command -v dmesg &> /dev/null; then
lockup_count=$(dmesg -T 2>/dev/null | grep -i "soft lockup" | wc -l)
fi
output_result "SOFT_LOCKUP_COUNT" "$lockup_count"
if [ "$lockup_count" -gt 0 ]; then
output_result "SOFT_LOCKUP_STATUS" "严重"
echo "ERROR:检测到软锁定事件"
else
output_result "SOFT_LOCKUP_STATUS" "正常"
fi
}
# 检测硬件错误(MCE)
check_hardware_errors() {
local mce_count=0
if command -v dmesg &> /dev/null; then
mce_count=$(dmesg -T 2>/dev/null | grep -i "machine check" | wc -l)
fi
# 检查 /dev/mcelog 是否存在
if [ -c /dev/mcelog ]; then
output_result "MCE_DEVICE" "存在"
else
output_result "MCE_DEVICE" "不存在"
fi
output_result "HARDWARE_ERRORS" "$mce_count"
if [ "$mce_count" -gt 0 ]; then
output_result "HARDWARE_STATUS" "严重"
echo "ERROR:检测到硬件错误"
else
output_result "HARDWARE_STATUS" "正常"
fi
}
# ==================== 主检测流程 ====================
main() {
log_info "开始OOM和内核异常检测..."
# 执行各项检测
check_oom_killer
check_core_dumps
check_readonly_fs
check_kernel_errors
check_soft_lockup
check_hardware_errors
log_info "OOM和内核异常检测完成"
}
# 执行主函数
main
#!/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
#!/bin/bash
################################################################################
# 网络连接检测模块
# 功能: 检测TCP连接状态、网络接口、端口连接、网络错误等
# 作者: 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
# ==================== 检测函数 ====================
# 检测TCP连接状态统计
check_tcp_connections() {
local established=0 time_wait=0 close_wait=0
local tw_status cw_status
# 从 /proc/net/tcp 读取TCP连接状态
if [ -f /proc/net/tcp ]; then
# TCP状态码: 01=ESTABLISHED, 06=TIME_WAIT, 08=CLOSE_WAIT
local tcp_stats=$(cat /proc/net/tcp | awk '{print $4}' | sort | uniq -c | sort -rn)
established=$(echo "$tcp_stats" | grep "01" | awk '{sum+=$1} END {print sum+0}')
time_wait=$(echo "$tcp_stats" | grep "06" | awk '{sum+=$1} END {print sum+0}')
close_wait=$(echo "$tcp_stats" | grep "08" | awk '{sum+=$1} END {print sum+0}')
fi
output_result "TCP_ESTABLISHED" "$established"
# TIME_WAIT状态判断
if [ "$time_wait" -ge 5000 ]; then
tw_status="严重"
elif [ "$time_wait" -ge 500 ]; then
tw_status="警告"
else
tw_status="正常"
fi
output_result "TCP_TIME_WAIT" "$time_wait"
output_result "TCP_TIME_WAIT_STATUS" "$tw_status"
if [ "$tw_status" != "正常" ]; then
echo "ERROR:TIME_WAIT连接过多: ${time_wait}"
fi
# CLOSE_WAIT状态判断
if [ "$close_wait" -ge 500 ]; then
cw_status="严重"
elif [ "$close_wait" -ge 100 ]; then
cw_status="警告"
else
cw_status="正常"
fi
output_result "TCP_CLOSE_WAIT" "$close_wait"
output_result "TCP_CLOSE_WAIT_STATUS" "$cw_status"
if [ "$cw_status" != "正常" ]; then
echo "ERROR:CLOSE_WAIT连接过多: ${close_wait}"
fi
}
# 检测网络接口状态
check_network_interfaces() {
local up_count=0
local total_count=0
# 使用 ip 命令获取网络接口状态
if command -v ip &> /dev/null; then
up_count=$(ip link show 2>/dev/null | grep -c "state UP" || echo "0")
total_count=$(ip link show 2>/dev/null | grep -c "^[0-9]" || echo "0")
elif [ -f /proc/net/dev ]; then
# 备用方案:从 /proc/net/dev 统计
total_count=$(tail -n +3 /proc/net/dev | wc -l)
fi
output_result "NET_INTERFACE_UP" "$up_count"
output_result "NET_INTERFACE_TOTAL" "$total_count"
if [ "$up_count" -eq 0 ]; then
output_result "NET_INTERFACE_STATUS" "严重"
echo "ERROR:没有活跃的网络接口"
else
output_result "NET_INTERFACE_STATUS" "正常"
fi
}
# 检测关键端口连接数
check_port_connections() {
local ports=("8306:MySQL" "6379:Redis" "1883:EMQX_MQTT" "8883:EMQX_SSL" "3306:MySQL_Default" "80:HTTP" "443:HTTPS")
for port_info in "${ports[@]}"; do
local port=$(echo "$port_info" | cut -d: -f1)
local name=$(echo "$port_info" | cut -d: -f2)
local conn_count=0
# 使用 ss 或 netstat 统计端口连接数
if command -v ss &> /dev/null; then
conn_count=$(ss -tnp 2>/dev/null | grep ":$port " | grep ESTAB | wc -l)
elif command -v netstat &> /dev/null; then
conn_count=$(netstat -tn 2>/dev/null | grep ":$port " | grep ESTABLISHED | wc -l)
fi
local key_name="PORT_${name}"
output_result "${key_name}_CONNECTIONS" "$conn_count"
done
}
# 检测网络错误统计
check_network_errors() {
local has_errors=0
# 使用 ip 命令获取网络错误统计
if command -v ip &> /dev/null; then
local error_output
error_output=$(ip -s link show 2>/dev/null | grep -E "errors|dropped")
if [ -n "$error_output" ]; then
# 检查是否有错误
if echo "$error_output" | grep -q "[1-9]"; then
has_errors=1
fi
fi
fi
if [ "$has_errors" -eq 1 ]; then
output_result "NET_ERRORS" "存在"
output_result "NET_ERRORS_STATUS" "警告"
else
output_result "NET_ERRORS" "无"
output_result "NET_ERRORS_STATUS" "正常"
fi
}
# 检测网络流量统计
check_network_traffic() {
# 从 /proc/net/dev 获取网络流量
if [ -f /proc/net/dev ]; then
# 获取主要网络接口的流量统计
local traffic_info=$(tail -n +3 /proc/net/dev | head -5)
if [ -n "$traffic_info" ]; then
output_result "NET_TRAFFIC" "已获取"
else
output_result "NET_TRAFFIC" "获取失败"
fi
fi
}
# 检测DNS解析
check_dns_resolution() {
local dns_status="正常"
local test_domain="www.baidu.com"
if command -v nslookup &> /dev/null; then
if ! nslookup "$test_domain" &> /dev/null; then
dns_status="警告"
fi
elif command -v host &> /dev/null; then
if ! host "$test_domain" &> /dev/null; then
dns_status="警告"
fi
elif command -v getent &> /dev/null; then
if ! getent hosts "$test_domain" &> /dev/null; then
dns_status="警告"
fi
fi
output_result "DNS_RESOLUTION" "$dns_status"
if [ "$dns_status" != "正常" ]; then
echo "ERROR:DNS解析可能存在问题"
fi
}
# 检测网络配置
check_network_config() {
local hostname gateway
# 获取主机名
hostname=$(hostname -f 2>/dev/null || hostname)
output_result "NET_HOSTNAME" "$hostname"
# 获取默认网关
if command -v ip &> /dev/null; then
gateway=$(ip route | grep default | awk '{print $3}' | head -1)
elif command -v route &> /dev/null; then
gateway=$(route -n | grep "^0.0.0.0" | awk '{print $2}' | head -1)
fi
if [ -n "$gateway" ]; then
output_result "NET_GATEWAY" "$gateway"
output_result "NET_GATEWAY_STATUS" "正常"
else
output_result "NET_GATEWAY" "未配置"
output_result "NET_GATEWAY_STATUS" "警告"
fi
}
# 检测TCP参数配置
check_tcp_params() {
# 检查关键TCP参数
local tcp_tw_reuse=""
local tcp_tw_recycle=""
local tcp_fin_timeout=""
if [ -f /proc/sys/net/ipv4/tcp_tw_reuse ]; then
tcp_tw_reuse=$(cat /proc/sys/net/ipv4/tcp_tw_reuse 2>/dev/null)
fi
if [ -f /proc/sys/net/ipv4/tcp_tw_recycle ]; then
tcp_tw_recycle=$(cat /proc/sys/net/ipv4/tcp_tw_recycle 2>/dev/null)
fi
if [ -f /proc/sys/net/ipv4/tcp_fin_timeout ]; then
tcp_fin_timeout=$(cat /proc/sys/net/ipv4/tcp_fin_timeout 2>/dev/null)
fi
[ -n "$tcp_tw_reuse" ] && output_result "TCP_TW_REUSE" "$tcp_tw_reuse"
[ -n "$tcp_tw_recycle" ] && output_result "TCP_TW_RECYCLE" "$tcp_tw_recycle"
[ -n "$tcp_fin_timeout" ] && output_result "TCP_FIN_TIMEOUT_PARAM" "$tcp_fin_timeout"
}
# 检测TCP扩展统计
check_tcp_extended_stats() {
if [ -f /proc/net/snmp ]; then
# 获取TCP扩展统计
local tcp_stats=""
tcp_stats=$(cat /proc/net/snmp 2>/dev/null | grep "^Tcp:" | head -1)
if [ -n "$tcp_stats" ]; then
output_result "TCP_EXT_STATS" "$(echo "$tcp_stats" | cut -c1-200)" # 截取前200字符
fi
fi
}
# 检测ARP表
check_arp_table() {
local arp_count=""
local arp_entries=""
if command -v ip &> /dev/null; then
arp_entries=$(ip neigh show 2>/dev/null | grep -v "FAILED" | head -10 | tr '\n' ',' | sed 's/,$//')
arp_count=$(ip neigh show 2>/dev/null | grep -v "FAILED" | wc -l)
fi
[ -n "$arp_entries" ] && output_result "ARP_ENTRIES" "$arp_entries"
[ -n "$arp_count" ] && output_result "ARP_COUNT" "$arp_count"
}
# 检测路由表
check_routing_table() {
if command -v ip &> /dev/null; then
local route_count=""
route_count=$(ip route show 2>/dev/null | wc -l)
output_result "ROUTES_COUNT" "$route_count"
fi
}
# 检测Socket统计
check_socket_stats() {
if [ -f /proc/net/sockstat ]; then
local sockstat
sockstat=$(cat /proc/net/sockstat 2>/dev/null | tr '\n' ',' | sed 's/,$//')
if [ -n "$sockstat" ]; then
output_result "SOCKET_STATS" "$sockstat"
fi
fi
}
# 检测网络带宽统计详情
check_network_bandwidth() {
if [ -f /proc/net/dev ]; then
# 获取主要网络接口的带宽统计
local bandwidth_info=""
bandwidth_info=$(tail -n +3 /proc/net/dev | head -3 | awk '{print $1":"$2":"$10}' | tr '\n' ',' | sed 's/,$//')
if [ -n "$bandwidth_info" ]; then
output_result "NET_BANDWIDTH_DETAIL" "$bandwidth_info"
fi
fi
}
# 检测监听队列积压
check_listen_queue() {
if command -v ss &> /dev/null; then
# 检查监听队列积压情况
local queue_full=""
queue_full=$(ss -lnt 2>/dev/null | awk '{print $6}' | grep -v "0" | head -5)
if [ -n "$queue_full" ]; then
output_result "LISTEN_QUEUE_BACKLOG" "$queue_full"
else
output_result "LISTEN_QUEUE_BACKLOG" "正常"
fi
else
output_result "LISTEN_QUEUE_BACKLOG" "ss不可用"
fi
}
# 检测网关连通性
check_gateway_connectivity() {
local gateway=""
local ping_status="未测试"
# 获取默认网关
if command -v ip &> /dev/null; then
gateway=$(ip route | grep default | awk '{print $3}' | head -1)
elif command -v route &> /dev/null; then
gateway=$(route -n | grep "^0.0.0.0" | awk '{print $2}' | head -1)
fi
if [ -n "$gateway" ] && command -v ping &> /dev/null; then
# ping网关3次,每次超时1秒
if ping -c 3 -W 1 "$gateway" &>/dev/null; then
ping_status="正常"
else
ping_status="异常"
fi
fi
output_result "GATEWAY_PING_STATUS" "$ping_status"
}
# 检测容器间网络连通性
check_container_network() {
# 检查Docker容器间网络连通性
if command -v docker &> /dev/null; then
# ping uemqx容器
local uemqx_ip=""
uemqx_ip=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' uemqx 2>/dev/null | head -1)
if [ -n "$uemqx_ip" ] && command -v ping &> /dev/null; then
if ping -c 1 -W 1 "$uemqx_ip" &>/dev/null; then
output_result "CONTAINER_NETWORK_TO_EMQX" "正常"
else
output_result "CONTAINER_NETWORK_TO_EMQX" "异常"
fi
fi
fi
}
# ==================== 主检测流程 ====================
main() {
log_info "开始网络连接检测..."
# 执行各项检测
check_tcp_connections
check_network_interfaces
check_port_connections
check_network_errors
check_network_traffic
check_dns_resolution
check_network_config
check_tcp_params
check_tcp_extended_stats
check_arp_table
check_routing_table
check_socket_stats
check_network_bandwidth
check_listen_queue
check_gateway_connectivity
check_container_network
log_info "网络连接检测完成"
}
# 执行主函数
main
#!/bin/bash
################################################################################
# 定时任务检测模块
# 功能: 检测crontab任务、systemd定时器等定时任务配置
# 作者: 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
# ==================== 检测函数 ====================
# 检测crontab任务
check_crontab() {
local crontab_count=0
local crontab_list=""
if command -v crontab &> /dev/null; then
# 获取当前用户的crontab
local crontab_output
crontab_output=$(crontab -l 2>/dev/null)
if [ -n "$crontab_output" ]; then
# 统计非注释行
crontab_count=$(echo "$crontab_output" | grep -v "^#" | grep -v "^$" | wc -l)
# 获取任务列表(前10个)
crontab_list=$(echo "$crontab_output" | grep -v "^#" | grep -v "^$" | head -10)
output_result "CRONTAB_COUNT" "$crontab_count"
if [ -n "$crontab_list" ]; then
output_result "CRONTAB_LIST" "已获取"
fi
else
output_result "CRONTAB_COUNT" "0"
output_result "CRONTAB_STATUS" "无任务"
fi
else
output_result "CRONTAB_STATUS" "未安装"
fi
output_result "CRONTAB_LEVEL" "正常"
}
# 检测systemd定时器
check_systemd_timers() {
local timer_count=0
local active_timers=0
if command -v systemctl &> /dev/null; then
# 获取定时器列表
local timer_list
timer_list=$(systemctl list-timers --no-pager 2>/dev/null | tail -n +2 | head -10)
if [ -n "$timer_list" ]; then
timer_count=$(echo "$timer_list" | wc -l)
active_timers=$(echo "$timer_list" | grep -c "ACTIVE" || echo "0")
output_result "SYSTEMD_TIMERS" "$timer_count"
output_result "SYSTEMD_TIMERS_ACTIVE" "$active_timers"
else
output_result "SYSTEMD_TIMERS" "0"
fi
else
output_result "SYSTEMD_TIMERS" "systemctl不可用"
fi
output_result "SYSTEMD_TIMERS_LEVEL" "正常"
}
# 检测anacron任务
check_anacron() {
local anacron_status="未安装"
if [ -f /etc/anacrontab ]; then
anacron_status="已配置"
# 统计任务数量
local anacron_count
anacron_count=$(grep -v "^#" /etc/anacrontab 2>/dev/null | grep -v "^$" | wc -l)
output_result "ANACRON_COUNT" "$anacron_count"
else
output_result "ANACRON_STATUS" "$anacron_status"
fi
}
# 检测at任务
check_at_jobs() {
local at_count=0
if command -v at &> /dev/null; then
# 获取at任务列表
at_count=$(at -l 2>/dev/null | wc -l)
output_result "AT_JOBS" "$at_count"
else
output_result "AT_JOBS" "未安装"
fi
output_result "AT_JOBS_LEVEL" "正常"
}
# 检测crond服务状态
check_crond_status() {
local crond_status="未知"
local crond_service=""
if command -v systemctl &> /dev/null; then
# 检查crond服务
if systemctl is-active cron &> /dev/null; then
crond_service="cron"
crond_status="运行中"
elif systemctl is-active crond &> /dev/null; then
crond_service="crond"
crond_status="运行中"
else
crond_status="未运行"
fi
fi
output_result "CROND_SERVICE" "$crond_service"
output_result "CROND_STATUS" "$crond_status"
if [ "$crond_status" = "未运行" ]; then
output_result "CROND_LEVEL" "警告"
else
output_result "CROND_LEVEL" "正常"
fi
}
# 检测系统级crontab
check_system_crontab() {
local system_cron_count=0
local cron_dirs=("/etc/cron.d" "/etc/cron.hourly" "/etc/cron.daily" "/etc/cron.weekly" "/etc/cron.monthly")
for dir in "${cron_dirs[@]}"; do
if [ -d "$dir" ]; then
local count
count=$(find "$dir" -type f 2>/dev/null | wc -l)
system_cron_count=$((system_cron_count + count))
fi
done
output_result "SYSTEM_CRON_COUNT" "$system_cron_count"
# 检查/etc/crontab
if [ -f /etc/crontab ]; then
local crontab_entries
crontab_entries=$(grep -v "^#" /etc/crontab 2>/dev/null | grep -v "^$" | wc -l)
output_result "ETC_CRONTAB_ENTRIES" "$crontab_entries"
fi
}
# 检测定时任务日志
check_cron_logs() {
local cron_errors=0
if command -v journalctl &> /dev/null; then
# 检查cron相关日志中的错误
cron_errors=$(journalctl --since '24 hours ago' -u cron -u crond 2>/dev/null | grep -ci "error" || echo "0")
fi
output_result "CRON_ERRORS_24H" "$cron_errors"
if [ "$cron_errors" -gt 10 ]; then
output_result "CRON_LOGS_LEVEL" "警告"
else
output_result "CRON_LOGS_LEVEL" "正常"
fi
}
# ==================== 主检测流程 ====================
main() {
log_info "开始定时任务检测..."
# 执行各项检测
check_crontab
check_systemd_timers
check_anacron
check_at_jobs
check_crond_status
check_system_crontab
check_cron_logs
log_info "定时任务检测完成"
}
# 执行主函数
main
#!/bin/bash
################################################################################
# 端口服务检测模块
# 功能: 检测关键服务端口的监听状态
# 作者: 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
# ==================== 端口配置 ====================
# 端口格式: "名称:端口:关键标志"
declare -a PORT_CONFIG=(
"SSH:22:1"
"MySQL:8306:1"
"Redis:6379:1"
"EMQX_MQTT:1883:1"
"EMQX_SSL:8883:0"
"EMQX_WS:8083:0"
"Java_Web:8080:1"
"HTTPS:443:1"
"Java_Admin:8999:1"
"Python:8000:0"
"FastDFS_Tracker:22122:0"
"FastDFS_Storage:23000:0"
"HTTP:80:0"
"MySQL_Default:3306:0"
"Python_Web:8081:0"
)
# ==================== 检测函数 ====================
# 检测单个端口状态
check_single_port() {
local port_name=$1
local port_num=$2
local is_critical=$3
local is_listening=0
local listen_address=""
local process_name=""
# 使用 ss 命令检测
if command -v ss &> /dev/null; then
local port_info
port_info=$(ss -tlnp 2>/dev/null | grep ":$port_num " | grep LISTEN)
if [ -n "$port_info" ]; then
is_listening=1
listen_address=$(echo "$port_info" | awk '{print $4}' | head -1)
# 尝试获取进程名
process_name=$(echo "$port_info" | grep -oP 'pid=\K[0-9]+.*' | head -1)
fi
# 备用方案:使用 netstat
elif command -v netstat &> /dev/null; then
local port_info
port_info=$(netstat -tln 2>/dev/null | grep ":$port_num " | grep LISTEN)
if [ -n "$port_info" ]; then
is_listening=1
listen_address=$(echo "$port_info" | awk '{print $4}' | head -1)
fi
# 最后备用方案:直接检查 /proc/net/tcp
elif [ -f /proc/net/tcp ]; then
# 将端口号转换为16进制
local port_hex=$(printf "%04X" $port_num)
if grep -q ":$port_hex " /proc/net/tcp 2>/dev/null; then
is_listening=1
fi
fi
# 确定状态级别
local status_level
if [ $is_listening -eq 1 ]; then
status_level="正常"
else
if [ $is_critical -eq 1 ]; then
status_level="严重"
else
status_level="警告"
fi
fi
# 输出结果
local key_name="PORT_${port_name}"
output_result "${key_name}_NUMBER" "$port_num"
output_result "${key_name}_STATUS" "$status_level"
if [ $is_listening -eq 1 ]; then
output_result "${key_name}_LISTENING" "是"
if [ -n "$listen_address" ]; then
output_result "${key_name}_ADDRESS" "$listen_address"
fi
else
output_result "${key_name}_LISTENING" "否"
echo "ERROR:端口${port_name}(${port_num})未监听"
fi
}
# 检测所有配置的端口
check_all_ports() {
local total_ports=${#PORT_CONFIG[@]}
local listening_count=0
local critical_down=0
for port_info in "${PORT_CONFIG[@]}"; do
IFS=':' read -r name port critical <<< "$port_info"
check_single_port "$name" "$port" "$critical"
# 统计监听中的端口
local key_name="PORT_${name}_LISTENING"
# 重新检查端口状态用于统计(简化版)
if command -v ss &> /dev/null; then
if ss -tlnp 2>/dev/null | grep -q ":$port "; then
listening_count=$((listening_count + 1))
else
if [ "$critical" -eq 1 ]; then
critical_down=$((critical_down + 1))
fi
fi
fi
done
output_result "PORT_TOTAL" "$total_ports"
output_result "PORT_LISTENING" "$listening_count"
output_result "PORT_DOWN" "$((total_ports - listening_count))"
if [ $critical_down -gt 0 ]; then
output_result "PORT_CRITICAL_DOWN" "$critical_down"
output_result "PORT_OVERALL_STATUS" "严重"
elif [ $listening_count -lt $((total_ports / 2)) ]; then
output_result "PORT_OVERALL_STATUS" "警告"
else
output_result "PORT_OVERALL_STATUS" "正常"
fi
}
# 检测端口占用情况
check_port_usage() {
local total_listening=0
local total_ports=65535
if command -v ss &> /dev/null; then
total_listening=$(ss -tln 2>/dev/null | grep -c LISTEN || echo "0")
fi
output_result "PORT_LISTENING_COUNT" "$total_listening"
if [ "$total_listening" -gt 100 ]; then
output_result "PORT_USAGE_LEVEL" "警告"
else
output_result "PORT_USAGE_LEVEL" "正常"
fi
}
# 检测特权端口(<1024)
check_privileged_ports() {
local priv_count=0
if command -v ss &> /dev/null; then
priv_count=$(ss -tlnp 2>/dev/null | awk '{print $4}' | grep -oE ':[0-9]+' | sed 's/://' | awk '$1 < 1024' | wc -l)
fi
output_result "PRIVILEGED_PORTS" "$priv_count"
}
# 检测端口复用情况
check_port_reuse() {
local reuse_count=0
if command -v ss &> /dev/null; then
# 检查SO_REUSEADDR端口
reuse_count=$(ss -tlnp 2>/dev/null | grep -c "0.0.0.0:" || echo "0")
fi
output_result "PORT_REUSE_COUNT" "$reuse_count"
}
# 检测IPv6端口监听
check_ipv6_ports() {
local ipv6_count=0
if command -v ss &> /dev/null; then
ipv6_count=$(ss -tln6 2>/dev/null | grep -c LISTEN || echo "0")
fi
output_result "IPV6_PORTS" "$ipv6_count"
}
# ==================== 主检测流程 ====================
main() {
log_info "开始端口服务检测..."
# 执行各项检测
check_all_ports
check_port_usage
check_privileged_ports
check_port_reuse
check_ipv6_ports
log_info "端口服务检测完成"
}
# 执行主函数
main
...@@ -61,13 +61,33 @@ ALL_MODULES: List[CheckModule] = [ ...@@ -61,13 +61,33 @@ ALL_MODULES: List[CheckModule] = [
{SUITE_QUICK, SUITE_FULL}, "03_memory_check.sh"), {SUITE_QUICK, SUITE_FULL}, "03_memory_check.sh"),
CheckModule("04_disk_check", "磁盘检测", "system", CheckModule("04_disk_check", "磁盘检测", "system",
{SUITE_QUICK, SUITE_FULL}, "04_disk_check.sh"), {SUITE_QUICK, SUITE_FULL}, "04_disk_check.sh"),
CheckModule("05_oom_check", "OOM和内核异常检测", "system",
{SUITE_FULL}, "05_oom_check.sh"),
CheckModule("06_process_check", "进程检测", "system",
{SUITE_FULL}, "06_process_check.sh"),
CheckModule("07_network_check", "网络检测", "system",
{SUITE_FULL}, "07_network_check.sh"),
CheckModule("11_scheduled_tasks", "计划任务检测", "system",
{SUITE_FULL}, "11_scheduled_tasks.sh"),
CheckModule("12_port_check", "端口检测", "system",
{SUITE_FULL}, "12_port_check.sh"),
# ---- service 类 ---- # ---- service 类 ----
CheckModule("20_docker_basic", "Docker基础", "service", CheckModule("20_docker_basic", "Docker基础", "service",
{SUITE_QUICK, SUITE_FULL}, "20_docker_basic.sh"), {SUITE_QUICK, SUITE_FULL}, "20_docker_basic.sh"),
CheckModule("21_docker_deep", "Docker深度检测", "service",
{SUITE_FULL}, "21_docker_deep.sh"),
CheckModule("22_mysql_basic", "MySQL基础", "service", CheckModule("22_mysql_basic", "MySQL基础", "service",
{SUITE_FULL}, "22_mysql_basic.sh"), {SUITE_FULL}, "22_mysql_basic.sh"),
CheckModule("23_mysql_depth", "MySQL深度检测", "service",
{SUITE_FULL}, "23_mysql_depth.sh"),
CheckModule("24_redis_basic", "Redis基础", "service", CheckModule("24_redis_basic", "Redis基础", "service",
{SUITE_FULL}, "24_redis_basic.sh"), {SUITE_FULL}, "24_redis_basic.sh"),
CheckModule("25_redis_depth", "Redis深度检测", "service",
{SUITE_FULL}, "25_redis_depth.sh"),
CheckModule("37_ustorage_check", "UStorage容器监测", "service",
{SUITE_FULL}, "37_ustorage_check.sh"),
CheckModule("38_utracker_check", "UTracker容器监测", "service",
{SUITE_FULL}, "38_utracker_check.sh"),
] ]
_BY_ID: Dict[str, CheckModule] = {m.id: m for m in ALL_MODULES} _BY_ID: Dict[str, CheckModule] = {m.id: m for m in ALL_MODULES}
......
...@@ -159,4 +159,180 @@ DISPLAY_NAMES: Dict[str, str] = { ...@@ -159,4 +159,180 @@ DISPLAY_NAMES: Dict[str, str] = {
"REDIS_AOF": "Redis AOF状态", "REDIS_AOF": "Redis AOF状态",
"REDIS_TOTAL_CONNECTIONS": "Redis总连接数", "REDIS_TOTAL_CONNECTIONS": "Redis总连接数",
"REDIS_TOTAL_COMMANDS": "Redis总命令数", "REDIS_TOTAL_COMMANDS": "Redis总命令数",
# ---- 05 OOM和内核异常检测 ----
"OOM_COUNT": "OOM事件总数",
"OOM_RECENT_DAYS": "近7天OOM事件",
"OOM_STATUS": "OOM状态",
"CORE_DUMP_COUNT": "Core dump文件数",
"CORE_DUMP_STATUS": "Core dump状态",
"READONLY_FS_COUNT": "只读文件系统数",
"READONLY_FS_STATUS": "只读文件系统状态",
"KERNEL_ERRORS": "内核错误数",
"KERNEL_STATUS": "内核状态",
"SOFT_LOCKUP_COUNT": "软锁定事件数",
"SOFT_LOCKUP_STATUS": "软锁定状态",
"HARDWARE_ERRORS": "硬件错误数",
"HARDWARE_STATUS": "硬件状态",
"MCE_DEVICE": "MCE设备",
# ---- 06 进程检测 ----
"PROCESS_COUNT": "进程总数",
"THREAD_COUNT": "线程总数",
"THREAD_STATUS": "线程状态",
"FD_ALLOCATED": "已分配文件描述符",
"FD_MAXIMUM": "最大文件描述符",
"FD_STATUS": "文件描述符状态",
"FD_USAGE": "文件描述符使用率",
"ZOMBIE_COUNT": "僵尸进程数",
"ZOMBIE_STATUS": "僵尸进程状态",
"ORPHAN_COUNT": "孤儿进程数",
"PROCESS_ORPHAN_COUNT": "孤儿进程数",
"PROCESS_ORPHAN_STATUS": "孤儿进程状态",
"UNINTERRUPTIBLE_COUNT": "不可中断进程数",
"UNINTERRUPTIBLE_STATUS": "不可中断进程状态",
"UNINTERRUPTIBLE_PROCESSES": "不可中断进程列表",
"PROCESS_TOP10_CPU": "CPU占用TOP10进程",
"PROCESS_TOP10_MEMORY": "内存占用TOP10进程",
"PROCESS_CONNECTIONS_TOP5": "连接数TOP5进程",
"PROCESS_OPEN_FILES_TOP5": "打开文件数TOP5进程",
"PROCESS_EXE_PATHS_TOP10": "可执行路径TOP10",
"PROCESS_LONGEST_RUNNING": "最长运行进程",
# ---- 07 网络检测 ----
"NET_INTERFACE_TOTAL": "网卡总数",
"NET_INTERFACE_UP": "活动网卡数",
"NET_INTERFACE_STATUS": "网卡状态",
"NET_HOSTNAME": "网络主机名",
"NET_GATEWAY": "网关地址",
"NET_GATEWAY_STATUS": "网关状态",
"GATEWAY_PING_STATUS": "网关Ping状态",
"DNS_RESOLUTION": "DNS解析状态",
"NET_TRAFFIC": "网络流量",
"NET_BANDWIDTH_DETAIL": "带宽详情",
"NET_ERRORS": "网络错误数",
"NET_ERRORS_STATUS": "网络错误状态",
"ROUTES_COUNT": "路由条目数",
"ARP_COUNT": "ARP条目数",
"ARP_ENTRIES": "ARP表项",
"TCP_ESTABLISHED": "TCP已建立连接数",
"TCP_TIME_WAIT": "TCP TIME_WAIT数",
"TCP_TIME_WAIT_STATUS": "TCP TIME_WAIT状态",
"TCP_CLOSE_WAIT": "TCP CLOSE_WAIT数",
"TCP_CLOSE_WAIT_STATUS": "TCP CLOSE_WAIT状态",
"TCP_TW_RECYCLE": "TCP TW回收",
"TCP_TW_REUSE": "TCP TW复用",
"TCP_FIN_TIMEOUT_PARAM": "TCP FIN超时参数",
"TCP_EXT_STATS": "TCP扩展统计",
"LISTEN_QUEUE_BACKLOG": "监听队列积压",
"SOCKET_STATS": "Socket统计",
"IPV6_PORTS": "IPv6端口数",
"CONTAINER_NETWORK_TO_EMQX": "容器到EMQX网络",
"LOAD_RATIO": "负载比率",
"LOAD_CORES": "负载核心数",
"LOAD_STATUS": "负载状态",
# ---- 11 计划任务检测 ----
"CRONTAB_COUNT": "Crontab任务数",
"CRONTAB_LIST": "Crontab任务列表",
"CRONTAB_STATUS": "Crontab状态",
"CRONTAB_LEVEL": "Crontab等级",
"ETC_CRONTAB_ENTRIES": "/etc/crontab条目",
"SYSTEM_CRON_COUNT": "系统Cron任务数",
"CROND_SERVICE": "Crond服务状态",
"CROND_STATUS": "Crond状态",
"CROND_LEVEL": "Crond等级",
"CRON_ERRORS_24H": "24小时Cron错误",
"CRON_LOGS_LEVEL": "Cron日志等级",
"ANACRON_COUNT": "Anacron任务数",
"ANACRON_STATUS": "Anacron状态",
"SYSTEMD_TIMERS": "Systemd定时器数",
"SYSTEMD_TIMERS_ACTIVE": "活跃Systemd定时器数",
"SYSTEMD_TIMERS_LEVEL": "Systemd定时器等级",
"AT_JOBS": "At任务数",
"AT_JOBS_LEVEL": "At任务等级",
# ---- 12 端口检测 ----
"PORT_TOTAL": "端口总数",
"PORT_LISTENING": "监听端口数",
"PORT_LISTENING_COUNT": "监听端口数",
"PORT_DOWN": "未监听端口数",
"PORT_CRITICAL_DOWN": "关键未监听端口数",
"PORT_OVERALL_STATUS": "端口总体状态",
"PORT_USAGE_LEVEL": "端口使用等级",
"PORT_REUSE_COUNT": "端口复用数",
"PRIVILEGED_PORTS": "特权端口",
# ---- 21 Docker深度检测 ----
"DOCKER_VERSION": "Docker版本",
"DOCKER_API_VERSION": "Docker API版本",
"DOCKER_STORAGE_DRIVER": "Docker存储驱动",
"DOCKER_IMAGES_COUNT": "Docker镜像数",
"DOCKER_IMAGES_DANGLING": "悬空镜像数",
"DOCKER_IMAGES_TOP5": "Docker镜像TOP5",
"DOCKER_NETWORK_COUNT": "Docker网络数",
"DOCKER_NETWORK_BRIDGE": "Docker Bridge网络数",
"DOCKER_NETWORK_OVERLAY": "Docker Overlay网络数",
"DOCKER_NETWORK_LIST": "Docker网络列表",
"DOCKER_VOLUMES_COUNT": "Docker卷数",
"DOCKER_VOLUMES_LIST": "Docker卷列表",
"DOCKER_BUILD_CACHE": "Docker构建缓存",
"DOCKER_DAEMON_CPU": "Docker守护进程CPU",
"DOCKER_DAEMON_MEM": "Docker守护进程内存",
"DOCKER_EVENTS_ERROR": "Docker错误事件",
"DOCKER_EVENTS_WARN": "Docker警告事件",
"DOCKER_EVENTS_LEVEL": "Docker事件等级",
# ---- 37 UStorage容器监测 ----
"USTORAGE_CONTAINER_NAME": "UStorage容器名",
"USTORAGE_CONTAINER_STATUS": "UStorage容器状态",
"USTORAGE_CONTAINER_LEVEL": "UStorage容器等级",
"USTORAGE_RESTART_COUNT": "UStorage重启次数",
"USTORAGE_RESTART_LEVEL": "UStorage重启等级",
"USTORAGE_UPTIME_SECONDS": "UStorage运行时长(秒)",
"USTORAGE_CPU_USAGE": "UStorage CPU使用率",
"USTORAGE_MEMORY_USAGE": "UStorage内存使用",
"USTORAGE_MEMORY_PERCENT": "UStorage内存使用率",
"USTORAGE_NET_IO": "UStorage网络IO",
"USTORAGE_BLOCK_IO": "UStorage磁盘IO",
"USTORAGE_CONTAINER_IP": "UStorage容器IP",
"USTORAGE_SERVICE_PORT": "UStorage服务端口",
"USTORAGE_HEALTH_CHECK": "UStorage健康检查",
"USTORAGE_RESPONSE_TIME": "UStorage响应时间",
"USTORAGE_HEALTH_LEVEL": "UStorage健康等级",
"USTORAGE_DATA_SIZE": "UStorage数据大小",
"USTORAGE_DISK_USAGE": "UStorage磁盘使用率",
"USTORAGE_DISK_LEVEL": "UStorage磁盘等级",
"USTORAGE_INODE_USAGE": "UStorage Inode使用率",
"USTORAGE_LOG_SIZE": "UStorage日志大小",
"USTORAGE_LOG_LEVEL": "UStorage日志等级",
# ---- 38 UTracker容器监测 ----
"UTRACKER_CONTAINER_NAME": "UTracker容器名",
"UTRACKER_CONTAINER_STATUS": "UTracker容器状态",
"UTRACKER_CONTAINER_LEVEL": "UTracker容器等级",
"UTRACKER_RESTART_COUNT": "UTracker重启次数",
"UTRACKER_RESTART_LEVEL": "UTracker重启等级",
"UTRACKER_UPTIME_SECONDS": "UTracker运行时长(秒)",
"UTRACKER_CPU_USAGE": "UTracker CPU使用率",
"UTRACKER_MEMORY_USAGE": "UTracker内存使用",
"UTRACKER_MEMORY_PERCENT": "UTracker内存使用率",
"UTRACKER_NET_IO": "UTracker网络IO",
"UTRACKER_BLOCK_IO": "UTracker磁盘IO",
"UTRACKER_CONTAINER_IP": "UTracker容器IP",
"UTRACKER_SERVICE_PORT": "UTracker服务端口",
"UTRACKER_HEALTH_CHECK": "UTracker健康检查",
"UTRACKER_RESPONSE_TIME": "UTracker响应时间",
"UTRACKER_HEALTH_LEVEL": "UTracker健康等级",
"UTRACKER_PROCESS_COUNT": "UTracker进程数",
"UTRACKER_THREAD_COUNT": "UTracker线程数",
"UTRACKER_FD_COUNT": "UTracker文件描述符数",
"UTRACKER_TCP_ESTABLISHED": "UTracker TCP已建立连接",
"UTRACKER_TCP_TIME_WAIT": "UTracker TCP TIME_WAIT",
"UTRACKER_TCP_CLOSE_WAIT": "UTracker TCP CLOSE_WAIT",
"UTRACKER_TCP_LEVEL": "UTracker TCP连接等级",
"UTRACKER_DISK_USAGE": "UTracker磁盘使用率",
"UTRACKER_DISK_LEVEL": "UTracker磁盘等级",
"UTRACKER_LOG_SIZE": "UTracker日志大小",
"UTRACKER_LOG_LEVEL": "UTracker日志等级",
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论