# 需求文档：P2 级检测模块移植（系统类型识别 + 平台服务检测 + 配置IP检测 + Console配置检测）

## 文档信息

- 创建时间：2026-07-22
- 需求来源：用户需求
- 关联模块：service_monitor
- 父需求：`PRD_需求文档_检测项丰富化移植.md`（阶段三）

---

## 1. 背景与目标

### 1.1 背景

服务监测模块已完成阶段一（补全缺失项 + 重构 depth 脚本）和阶段二（安全合规深度检测 + 中间件连接检测）。本次为阶段三，移植 P2 优先级的 4 个检测模块。

### 1.2 目标

移植参考目录（老版 PowerShell + Shell 巡检工具集）中的 4 个检测模块到本项目，适配现有架构：

1. **系统类型识别**：检测平台类型（新/旧）、容器类型（ujava/upython/upython_voice）、ujava 变体（unified/meeting）
2. **平台服务检测**：检测核心业务服务进程状态（auth/gateway/system/meeting/mqtt/quartz/message/extapi）+ 容器端口监听
3. **配置IP检测**：扫描配置文件中的未授权 IP 地址
4. **Console配置检测**：检测 `console=true` 配置项未关闭问题

---

## 2. 参考源文件分析

| 模块 | 参考源 | 行数 | 核心功能 |
|------|--------|------|---------|
| 系统类型识别 | `ServerProfile.psm1` | 422 | 平台类型、容器类型、ujava 变体识别 |
| 平台服务检测 | `ServiceCheck.psm1` + `check_server_health.sh` | 644 + 5013 | 服务进程检测、端口监听检测 |
| 配置IP检测 | `ConfigIPCheck.psm1` + `config_check.sh` | 613 + 304 | 配置文件 IP 扫描 |
| Console配置检测 | `check_server_health.sh` (第1582-1708行) | ~130 | console=true 检测 |

---

## 3. 模块一：系统类型识别（50_system_profile.sh）

### 3.1 检测项列表

| KEY | 中文名 | 说明 |
|-----|--------|------|
| `SYS_PROFILE_PLATFORM_TYPE` | 平台类型 | "new"(新统一平台) / "old"(传统平台) |
| `SYS_PROFILE_PLATFORM_TYPE_LEVEL` | 平台类型状态等级 | 正常/跳过 |
| `SYS_PROFILE_CONTAINER_TYPE` | 容器类型 | "ujava" / "upython" / "upython_voice" / "unknown" |
| `SYS_PROFILE_CONTAINER_TYPE_LEVEL` | 容器类型状态等级 | 正常/跳过 |
| `SYS_PROFILE_UJAVA_VARIANT` | ujava 变体 | "unified" / "meeting" / "none"（仅 ujava 容器有效） |
| `SYS_PROFILE_UJAVA_VARIANT_LEVEL` | ujava 变体状态等级 | 正常/跳过 |

### 3.2 检测逻辑

#### 3.2.1 平台类型检测

```bash
# 新平台：存在 /data/services 目录
if [ -d "/data/services" ]; then
    PLATFORM_TYPE="new"
else
    PLATFORM_TYPE="old"
fi
```

#### 3.2.2 容器类型检测

```bash
# 获取运行中的容器名称列表
containers=$(docker ps --format '{{.Names}}' 2>/dev/null)

# 正则匹配容器名
if echo "$containers" | grep -qE '^ujava[0-9]*$'; then
    CONTAINER_TYPE="ujava"
elif echo "$containers" | grep -qE '^upython_voice[0-9]*$'; then
    CONTAINER_TYPE="upython_voice"
elif echo "$containers" | grep -qE '^upython[0-9]*$'; then
    CONTAINER_TYPE="upython"
else
    CONTAINER_TYPE="unknown"
fi
```

#### 3.2.3 ujava 变体检测

```bash
# 仅 ujava 容器有效
if [ "$CONTAINER_TYPE" = "ujava" ]; then
    if [ -d "/var/www/java/unifiedPlatform" ]; then
        UJAVA_VARIANT="unified"
    else
        UJAVA_VARIANT="meeting"
    fi
else
    UJAVA_VARIANT="none"
fi
```

### 3.3 依赖

- 命令：`docker`、`ls`/`test`
- 无需凭据

---

## 4. 模块二：平台服务检测（51_service_check.sh）

### 4.1 检测项列表

#### 4.1.1 新平台 ujava 服务（容器内）

| KEY | 中文名 | 说明 |
|-----|--------|------|
| `SVC_CHECK_AUTH_STATUS` | 认证服务状态 | 运行中/未运行 |
| `SVC_CHECK_AUTH_STATUS_LEVEL` | 认证服务状态等级 | 正常/严重 |
| `SVC_CHECK_GATEWAY_STATUS` | 网关服务状态 | 运行中/未运行 |
| `SVC_CHECK_GATEWAY_STATUS_LEVEL` | 网关服务状态等级 | 正常/严重 |
| `SVC_CHECK_SYSTEM_STATUS` | 系统服务状态 | 运行中/未运行 |
| `SVC_CHECK_SYSTEM_STATUS_LEVEL` | 系统服务状态等级 | 正常/严重 |
| `SVC_CHECK_MEETING_STATUS` | 会议服务状态 | 运行中/未运行 |
| `SVC_CHECK_MEETING_STATUS_LEVEL` | 会议服务状态等级 | 正常/严重 |
| `SVC_CHECK_MQTT_STATUS` | MQTT 服务状态 | 运行中/未运行 |
| `SVC_CHECK_MQTT_STATUS_LEVEL` | MQTT 服务状态等级 | 正常/严重 |
| `SVC_CHECK_QUARTZ_STATUS` | 定时任务服务状态 | 运行中/未运行 |
| `SVC_CHECK_QUARTZ_STATUS_LEVEL` | 定时任务服务状态等级 | 正常/严重 |
| `SVC_CHECK_MESSAGE_STATUS` | 消息调度服务状态 | 运行中/未运行 |
| `SVC_CHECK_MESSAGE_STATUS_LEVEL` | 消息调度服务状态等级 | 正常/严重 |

#### 4.1.2 新平台 ujava 宿主机服务

| KEY | 中文名 | 说明 |
|-----|--------|------|
| `SVC_CHECK_EXTAPI_STATUS` | 对外API服务状态 | 运行中/未运行 |
| `SVC_CHECK_EXTAPI_STATUS_LEVEL` | 对外API服务状态等级 | 正常/严重 |

#### 4.1.3 传统平台 ujava 容器服务

| KEY | 中文名 | 说明 |
|-----|--------|------|
| `SVC_CHECK_NGINX_OLD_STATUS` | Nginx 服务状态(传统) | 运行中/未运行 |
| `SVC_CHECK_NGINX_OLD_STATUS_LEVEL` | Nginx 服务状态等级(传统) | 正常/严重 |
| `SVC_CHECK_MEETING_OLD_STATUS` | 会议服务状态(传统) | 运行中/未运行 |
| `SVC_CHECK_MEETING_OLD_STATUS_LEVEL` | 会议服务状态等级(传统) | 正常/严重 |

#### 4.1.4 传统平台 extapi 宿主机服务

| KEY | 中文名 | 说明 |
|-----|--------|------|
| `SVC_CHECK_EXTAPI_OLD_STATUS` | 对外API服务状态(传统) | 运行中/未运行 |
| `SVC_CHECK_EXTAPI_OLD_STATUS_LEVEL` | 对外API服务状态等级(传统) | 正常/严重 |

#### 4.1.5 upython/upython_voice 端口监听

| KEY | 中文名 | 说明 |
|-----|--------|------|
| `SVC_CHECK_PORT_8000_STATUS` | uWSGI 端口 8000 状态 | 监听/未监听 |
| `SVC_CHECK_PORT_8000_STATUS_LEVEL` | uWSGI 端口 8000 状态等级 | 正常/严重 |
| `SVC_CHECK_PORT_11211_STATUS` | Memcached 端口 11211 状态 | 监听/未监听 |
| `SVC_CHECK_PORT_11211_STATUS_LEVEL` | Memcached 端口 11211 状态等级 | 正常/严重 |
| `SVC_CHECK_PORT_8080_STATUS` | Nginx 端口 8080 状态 | 监听/未监听 |
| `SVC_CHECK_PORT_8080_STATUS_LEVEL` | Nginx 端口 8080 状态等级 | 正常/严重 |
| `SVC_CHECK_PORT_1883_STATUS` | MQTT 端口 1883 状态 | 监听/未监听 |
| `SVC_CHECK_PORT_1883_STATUS_LEVEL` | MQTT 端口 1883 状态等级 | 正常/严重 |

### 4.2 服务匹配模式配置

**新平台 ujava 服务**（在 `config.sh.template` 配置）：

| 服务 | 匹配模式 | 说明 |
|------|---------|------|
| auth | `ubains-auth.jar` | 认证服务 |
| gateway | `ubains-gateway.jar` | 网关服务 |
| system | `ubains-modules-system.jar` | 系统服务 |
| meeting | `ubains-meeting-inner-api-1.0-SNAPSHOT.jar` | 会议对内服务 |
| mqtt | `ubains-meeting-mqtt-1.0-SNAPSHOT.jar` | MQTT 服务 |
| quartz | `ubains-meeting-quartz-1.0-SNAPSHOT.jar` | 定时任务服务 |
| message | `ubains-meeting-message-scheduling-1.0-SNAPSHOT.jar` | 消息调度服务 |
| extapi | `ubains-meeting-api-1.0-SNAPSHOT.jar` | 对外 API 服务（宿主机） |

**传统平台服务**（匹配模式相同，路径不同）：
- 容器内服务：nginx + meeting
- 宿主机服务：extapi（路径 `/var/www/java/external-meeting-api`）

**端口列表**（按容器类型）：

| 容器类型 | 端口 | 进程 |
|---------|------|------|
| upython (新平台) | 8000, 11211 | uwsgi, memcached |
| upython_voice (新平台) | 8000, 11211, 8080, 1883, 9001 | uwsgi, memcached, nginx, mosquitto |
| upython (传统平台) | 8000, 11211, 8081, 8443, 8002 | uwsgi, memcached, nginx, httpd |

### 4.3 检测逻辑

#### 4.3.1 服务进程检测

```bash
# 容器内检测
count=$(docker exec "$container" ps aux 2>/dev/null | grep -F "$jar_pattern" | grep -v grep | wc -l)
if [ "$count" -gt 0 ]; then
    status="运行中"
else
    status="未运行"
fi

# 宿主机检测
count=$(ps aux 2>/dev/null | grep -F "$jar_pattern" | grep -v grep | wc -l)
```

#### 4.3.2 端口监听检测

```bash
# 容器内端口检测（优先用进程检查，避免容器内无 ss/netstat）
count=$(docker exec "$container" ps aux 2>/dev/null | grep "$process_name" | grep -v grep | wc -l)

# 或宿主机端口检测
ss -tlnp 2>/dev/null | grep -q ":$port "
```

### 4.4 依赖

- 命令：`docker`、`ps`、`ss`/`netstat`、`grep`
- 无需凭据（服务进程检测无需密码）
- 需要先运行 `50_system_profile.sh` 获取平台/容器类型（或脚本内部自行检测）

---

## 5. 模块三：配置IP检测（52_config_ip_check.sh）

### 5.1 检测项列表

| KEY | 中文名 | 说明 |
|-----|--------|------|
| `CFG_IP_STATUS` | 配置IP检测状态 | OK/WARN |
| `CFG_IP_STATUS_LEVEL` | 配置IP检测状态等级 | 正常/警告 |
| `CFG_IP_TOTAL_FILES` | 扫描文件数 | 整数 |
| `CFG_IP_UNAUTHORIZED_COUNT` | 未授权IP数 | 整数 |
| `CFG_IP_UNAUTHORIZED_LINES` | 未授权IP明细 | JSON 数组字符串 |

### 5.2 配置文件扫描路径

#### 5.2.1 新平台路径

| 目录 | 配置文件模式 |
|------|-------------|
| `/data/services/api/auth/auth-sso-auth/config` | *.yml, *.properties |
| `/data/services/api/auth/auth-sso-gateway/config` | *.yml, *.properties |
| `/data/services/api/auth/auth-sso-system/config` | *.yml, *.properties |
| `/data/services/api/java-meeting/java-meeting2.0/config` | *.yml, *.properties |
| `/data/services/api/java-meeting/java-meeting-extapi/config` | *.yml, *.properties |
| `/data/services/api/java-meeting/java-message-scheduling/config` | *.yml, *.properties |
| `/data/services/api/java-meeting/java-mqtt/config` | *.yml, *.properties |
| `/data/services/api/java-meeting/java-quartz/config` | *.yml, *.properties |
| `/data/services/api/python-cmdb` | *.yml, *.properties, config.py |
| `/data/services/web/pc/pc-vue2-ai/static` | config.js, config.json |
| `/data/services/web/mobile/mobile-vue2/static` | config.js, config.json |
| `/data/middleware/nginx/config` | *.conf |

#### 5.2.2 传统平台路径

| 目录 | 配置文件模式 |
|------|-------------|
| `/var/www/java/api-java-meeting2.0/config` | *.yml, *.properties |
| `/var/www/java/external-meeting-api/config` | *.yml, *.properties |
| `/var/www/java/ubains-web-2.0/static` | config.json |
| `/var/www/java/ubains-web-admin/static` | config.json |
| `/var/www/java/ubains-web-h5/static/h5` | config.js, config.json |
| `/var/www/java/nginx-conf.d` | *.conf |

### 5.3 检测逻辑

```bash
# IP 正则
IP_REGEX='([0-9]{1,3}\.){3}[0-9]{1,3}'

# 允许列表（服务器IP + 127.0.0.1 + 172.17.0.1）
ALLOWED_IPS="$SERVER_IP 127.0.0.1 172.17.0.1"

# 扫描配置文件
for dir in "${CONFIG_DIRS[@]}"; do
    while IFS= read -r file; do
        # 提取 IP
        ips=$(grep -oE "$IP_REGEX" "$file" 2>/dev/null | sort -u)
        for ip in $ips; do
            # 检查是否在允许列表
            if ! echo "$ALLOWED_IPS" | grep -qF "$ip"; then
                echo "未授权IP: $ip (文件: $file)"
            fi
        done
    done < <(find "$dir" -type f \( -name "*.yml" -o -name "*.properties" -o -name "config.js" -o -name "config.json" -o -name "*.conf" \) 2>/dev/null)
done
```

### 5.4 依赖

- 命令：`find`、`grep`、`sort`
- 需要服务器 IP（从 config.sh 获取 `SERVER_IP`）
- 需要先运行 `50_system_profile.sh` 获取平台类型

---

## 6. 模块四：Console配置检测（53_config_console_check.sh）

### 6.1 检测项列表

| KEY | 中文名 | 说明 |
|-----|--------|------|
| `CFG_CONSOLE_STATUS` | Console配置检测状态 | OK/WARN |
| `CFG_CONSOLE_STATUS_LEVEL` | Console配置检测状态等级 | 正常/警告 |
| `CFG_CONSOLE_TOTAL_FILES` | 扫描文件数 | 整数 |
| `CFG_CONSOLE_FOUND_COUNT` | 发现问题数 | 整数 |
| `CFG_CONSOLE_FOUND_FILES` | 问题文件列表 | JSON 数组字符串 |

### 6.2 配置文件扫描路径

复用配置 IP 检测的扫描路径（第 5.2 节）。

### 6.3 检测逻辑

```bash
# console=true 正则（不区分大小写）
CONSOLE_REGEX='console[[:space:]]*[:=][[:space:]]*true'

# 扫描配置文件
for dir in "${CONFIG_DIRS[@]}"; do
    while IFS= read -r file; do
        if grep -qiE "$CONSOLE_REGEX" "$file" 2>/dev/null; then
            echo "发现 console=true: $file"
        fi
    done < <(find "$dir" -type f \( -name "*.yml" -o -name "*.properties" -o -name "config.js" -o -name "config.json" \) 2>/dev/null)
done
```

### 6.4 行为约束

**只检测，不自动修复**（与用户确认的方案）：
- 发现 `console=true` 时标记为异常
- 不执行备份和 sed 替换
- 由人工确认后修复

### 6.5 依赖

- 命令：`find`、`grep`
- 需要先运行 `50_system_profile.sh` 获取平台类型

---

## 7. 技术方案

### 7.1 模块注册

在 `check_modules.py` 的 `ALL_MODULES` 列表新增 4 个 `CheckModule` 条目：

```python
CheckModule("50_system_profile", "系统类型识别", "system", {SUITE_FULL}, "50_system_profile.sh"),
CheckModule("51_service_check", "平台服务检测", "service", {SUITE_FULL}, "51_service_check.sh"),
CheckModule("52_config_ip_check", "配置IP检测", "system", {SUITE_FULL}, "52_config_ip_check.sh"),
CheckModule("53_config_console_check", "Console配置检测", "system", {SUITE_FULL}, "53_config_console_check.sh"),
```

### 7.2 显示名映射

在 `display_names.py` 新增 KEY 映射（共约 35 个）：
- 系统类型识别：6 个
- 平台服务检测：20+ 个
- 配置IP检测：5 个
- Console配置检测：5 个

### 7.3 阈值配置

在 `thresholds.py` 新增阈值（如有需要）：
- 服务状态：未运行 = 严重
- 端口状态：未监听 = 严重
- 未授权 IP 数：> 0 = 警告
- console=true 数：> 0 = 警告

### 7.4 配置模板

在 `config.sh.template` 新增：
- 服务匹配模式（`SVC_PATTERNS` 关联数组）
- 端口列表（`UPYTHON_PORTS`、`UPYTHON_VOICE_PORTS`）

### 7.5 模块依赖关系

```
50_system_profile.sh (平台/容器类型识别)
    ↓
51_service_check.sh (依赖容器类型选择检测项)
52_config_ip_check.sh (依赖平台类型选择扫描路径)
53_config_console_check.sh (依赖平台类型选择扫描路径)
```

**建议**：在 `check_modules.py` 的 `get_suite` 返回列表中，将 `50_system_profile` 排在最前，确保先执行。

---

## 8. 验收标准

| 标准 | 验证方法 |
|------|---------|
| 4 个检测脚本创建 | 语法检查 `bash -n` 通过 |
| check_modules.py 注册 | `get_suite('full')` 包含新模块 |
| display_names.py 映射 | 新 KEY 有中文名 |
| 服务检测逻辑正确 | 在 5.44 目标实际运行，服务状态与 `docker ps` 一致 |
| 配置 IP 检测正确 | 人工检查配置文件，对比检测结果 |
| Console 检测正确 | 人工检查配置文件，对比检测结果 |
| 单元测试通过 | pytest 全绿 |
| 已有测试不受影响 | 218 个测试全绿 |

---

## 9. 风险评估

| 风险 | 影响 | 缓解措施 |
|------|------|---------|
| 配置文件路径不存在 | 扫描结果为空 | 目录存在性检查，graceful 降级 |
| 容器名匹配失败 | 服务检测误判 | 使用 `grep -iE` 模糊匹配 + 默认值 |
| 新旧平台混合 | 检测项不适用 | 先识别平台类型，分支执行 |
| upython_voice 端口变化 | 端口检测误判 | 端口列表可配置化 |

---

## 10. 后续工作

- P3 级模块移植：文件权限、定时任务预期、FastDFS、Android 等
- 服务检测扩展：支持自定义服务匹配模式
- 配置 IP 检测增强：IP 白名单可配置化
