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

feat(monitor): 添加新统一平台后端服务监测与自愈功能

- 实现平台 API 可用性检查,异常时强制重启关键服务
- 添加容器内服务进程监测与自动拉起功能
- 集成 unacos 容器健康检查与按条件重启机制
- 实现宿主机对外服务(extapi)进程监测与拉起
- 添加宿主机 6060 端口监测,未监听时启动 malan
- 提供完整的日志输出与审计功能
- 支持定时执行的脚本部署与配置
上级 a0807c9d
# _PRD_后端服务监测需求文档.md
> 版本:V1.0
> 更新日期:2026-01-27
> 适用范围:新统一平台后端服务监测与自愈(容器内服务 + 宿主机对外服务 + 端口服务)
> 参考脚本:`自动化部署脚本/x86架构/新统一平台/定时脚本/ujava2-startup.sh`
---
## 1. 背景与目标
### 1.1 背景
新统一平台部署后,核心后端服务主要运行在 `ujava2` 容器中,且存在关键依赖组件 `unacos2`。同时,存在宿主机进程方式运行的“对外服务(extapi)”,以及宿主机端口 `6060``malan` 服务。
为降低故障恢复人工成本,需要引入定时监测与自动恢复能力。
### 1.2 目标
实现一套可定时执行的服务监测与自愈脚本,具备:
- 容器内关键服务进程监测与拉起
- unacos 容器健康检查与按条件重启
- 平台 API 可用性检查,异常时强制重启关键服务(gateway/auth/system)
- 宿主机对外服务(extapi)进程监测与拉起
- 宿主机 6060 端口监测,未监听时启动 malan
- 全流程日志输出与审计
---
## 2. 总体范围
### 2.1 纳入监测对象
1. **平台 API 可用性**
- URL:`https://192.168.5.44/platform/api/code`
2. **容器:`ujava2` 内部服务进程**
- auth、gateway、system、meeting2.0、meeting3.0、mqtt、quartz、message
3. **容器:`unacos2`**
- 容器存在性、运行状态、端口/服务可访问性(HTTP)
4. **宿主机对外服务(extapi)**
- jar:`ubains-meeting-api-1.0-SNAPSHOT.jar`
- 目录:`/data/services/api/java-meeting/java-meeting-extapi`
- 启动脚本:`run.sh`
5. **宿主机 6060 端口及 malan 服务**
- 端口:6060
- 目录:`/data/middleware/monitor`
- 启动命令:`./malan`
### 2.2 不在本期范围(可扩展)
- 指标型监控(CPU/内存/磁盘阈值与告警)
- 日志关键字检索与告警
- 统一告警通道(钉钉/邮件/短信)
- 容器资源限制/扩容策略
---
## 3. 术语说明
- **服务 key**:脚本内部用于标识服务的字符串,如 `gateway``meeting2.0`
- **关键服务**:gateway/auth/system(平台 API 异常时强制重启)
- **时间戳**:统一格式 `YYYY-MM-DD HH:MM:SS`
---
## 4. 功能需求
### 4.1 日志与审计
#### 4.1.1 日志文件
- 主日志:`/data/logs/ujava2-service-manager.log`
- unacos 专用日志:`/data/logs/unacos_restart.log`
#### 4.1.2 日志格式
每行必须包含:
- 时间戳:`timestamp()`
- 级别/动作标识:`[START] [STOP] [RUNNING] [STOPPED] [SUCCESS] [FAILED] [WARNING] [ERROR] [SUMMARY]`
- 目标对象:服务 key / 容器名 / 端口
示例:
- `2026-01-27 10:00:00 [RUNNING] gateway (PID: 1234)`
- `2026-01-27 10:00:10 [WARNING] 检测到 4 个服务停止,将重启unacos2容器`
---
### 4.2 平台 API 可用性检查(前置检查)
#### 4.2.1 检查逻辑
请求:
- `GET https://192.168.5.44/platform/api/code`
- `curl -k -m 10`
判定:
- HTTP 状态码必须为 `200`
- 响应内容必须包含:`"操作成功"``code:200`(允许空格)
#### 4.2.2 处理策略
- 若 API 检查失败:触发 **强制重启关键服务**(见 4.3)
- API 正常:继续后续检查流程
---
### 4.3 强制重启关键服务(gateway/auth/system)
#### 4.3.1 触发条件
- 平台 API 检查失败
#### 4.3.2 行为
对以下服务依次执行:
- `gateway`
- `auth`
- `system`
执行顺序:对每个服务执行 `stop_service``start_service`
输出汇总:`[SUMMARY] 已强制重启 X 个关键服务`
---
### 4.4 unacos2 健康检查与重启策略
#### 4.4.1 健康检查项
1. 容器存在:`docker inspect unacos2`
2. 容器运行:`docker inspect -f '{{.State.Status}}' unacos2 == running`
3. 服务可访问:`curl -m 5 http://localhost:8848/nacos/`
#### 4.4.2 重启触发条件
- 若 unacos 健康检查失败:立即重启 `unacos2`
- 若健康检查通过,但检测到停止服务数量 `stopped_count > 3`:重启 `unacos2`
#### 4.4.3 重启行为
- 执行:`docker restart unacos2`
- 记录到:`/data/logs/unacos_restart.log`
- 重启成功后等待:`sleep 30`
---
### 4.5 容器 ujava2 内部服务监测与自愈
#### 4.5.1 服务清单
| 服务key | jar标识/定位 | 启动脚本 |
| --- | --- | --- |
| auth | `ubains-auth.jar` | `/var/www/java/api/auth/auth-sso-auth/run.sh` |
| gateway | `ubains-gateway.jar` | `/var/www/java/api/auth/auth-sso-gatway/run.sh` |
| system | `ubains-modules-system.jar` | `/var/www/java/api/auth/auth-sso-system/run.sh` |
| meeting2.0 | `ubains-meeting-inner-api` + `java-meeting2.0/config` | `/var/www/java/api/java-meeting/java-meeting2.0/run.sh` |
| meeting3.0 | `ubains-meeting-inner-api` + `java-meeting3.0//config` | `/var/www/java/api/java-meeting/java-meeting3.0/run.sh` |
| mqtt | `ubains-meeting-mqtt-1.0-SNAPSHOT.jar` | `/var/www/java/api/java-meeting/java-mqtt/run.sh` |
| quartz | `ubains-meeting-quartz-1.0-SNAPSHOT.jar` | `/var/www/java/api/java-meeting/java-quartz/run.sh` |
| message | `ubains-meeting-message-scheduling-1.0-SNAPSHOT.jar` | `/var/www/java/api/java-meeting/java-message-scheduling/run.sh` |
> 注:meeting2.0/3.0 通过 ps 组合条件避免误匹配(脚本内为特判逻辑)。
#### 4.5.2 运行状态判定
- 获取 PID:通过 `docker exec ujava2` 在容器内 `ps aux | grep` 定位
- 判定运行:PID 非空 且 `ps -p $pid` 成功
#### 4.5.3 自愈动作:start_service
- 先 stop:若存在 PID 则 kill
- 启动:在容器内执行:
- `nohup <run.sh> > /var/log/<service_key>.log 2>&1 &`
- 等待启动:超时 30 秒
- 成功:输出 `[SUCCESS] service_key (PID: xxx)`
- 失败:输出 `[FAILED] service_key 启动超时`
#### 4.5.4 自愈策略:restart_problem_services
- 若发现某服务未运行:尝试 start_service
- 输出 `[SUMMARY] 已尝试重启 X 个服务`
#### 4.5.5 服务检查:check_services
- 输出本轮检查开始标识:`===== timestamp 服务状态检查 =====`
- 遍历全部服务输出 RUNNING/STOPPED
- 统计 STOPPED 数量 problems
- 调用 `restart_unacos_if_needed problems`
- 返回 problems 作为流程判断依据
---
### 4.6 宿主机对外服务 extapi 监测与自愈
#### 4.6.1 服务定义
- 服务名:`extapi`
- 进程识别:宿主机 `ps aux | grep -F 'ubains-meeting-api-1.0-SNAPSHOT.jar'`
- 运行目录:`/data/services/api/java-meeting/java-meeting-extapi`
- 启动脚本:`/data/services/api/java-meeting/java-meeting-extapi/run.sh`
#### 4.6.2 检查逻辑
- PID 非空且 `ps -p $pid` 成功 → RUNNING
- 否则 STOPPED
#### 4.6.3 重启逻辑
- kill 原进程(存在时)
- 校验 run.sh 存在
- `cd service_path && bash -c "source /etc/profile && ./run.sh" &`
- 等待启动 30 秒,成功则记录 PID
---
### 4.7 宿主机 6060 端口与 malan 监测与启动
#### 4.7.1 6060端口检查
端口监听判定满足任一:
- `netstat -tuln | grep ':6060 '`
- `ss -tuln | grep ':6060 '`
- `lsof -i:6060`
#### 4.7.2 启动 malan
- 目录:`/data/middleware/monitor`
- 启动命令:`bash -c "source /etc/profile && ./malan" &`
- 等待端口就绪 30 秒
- 成功:记录 `6060端口已监听`
- 失败:记录 `启动超时,6060端口未监听`
---
## 5. 主流程(顺序要求)
脚本主流程必须按以下顺序执行:
1. **平台 API 检查**
- 若失败 → `restart_critical_services`
2. **容器内服务检查**
- `check_services`
- 若返回非 0 → `restart_problem_services`
3. **宿主机对外服务检查**
- 若 STOPPED → `restart_host_extapi_service`
4. **6060 端口检查**
- 若未监听 → `start_malan_service`
最后输出:
- `===== timestamp 操作完成 =====`
---
## 6. 配置与可变项
| 配置项 | 默认/当前值 | 说明 |
| --- | --- | --- |
| ujava2容器名 | `ujava2` | 容器内服务执行目标 |
| unacos容器名 | `unacos2` | 依赖组件 |
| 平台 API URL | `https://192.168.5.44/platform/api/code` | 用于判断平台核心可用性 |
| extapi 目录 | `/data/services/api/java-meeting/java-meeting-extapi` | 宿主机对外服务 |
| malan 目录 | `/data/middleware/monitor` | 6060端口服务 |
| 服务启动等待 | 30s | start_service/restart_extapi/malan 统一超时 |
---
## 7. 异常处理与容错要求
1. 任何一步失败必须写日志(含原因/路径/命令关键点)。
2. `run.sh` 不存在必须明确提示(extapi、各容器服务)。
3. 重启 unacos 成功后必须等待 30 秒再继续(避免依赖未就绪)。
4. 端口检测必须兼容不同系统命令(netstat/ss/lsof 任一存在即可)。
---
## 8. 交付物
1. 定时脚本:
- `ujava2-startup.sh`
2. 日志文件输出:
- `/data/logs/ujava2-service-manager.log`
- `/data/logs/unacos_restart.log`
3. 使用说明:
- 需要通过 crontab 或 systemd timer 定时执行(频率由运维决定,如每 1~5 分钟一次)。
---
## 9. 验收标准
1. 当任一容器内服务停止时:
- 日志出现 `[STOPPED]` 与后续 `[START]/[SUCCESS]`,服务恢复运行。
2. 当 unacos2 不可访问或未运行时:
- 触发 `docker restart unacos2`,并记录到 unacos 日志。
3. 当停止服务数 > 3:
- 触发重启 unacos2,并记录原因。
4. 当 extapi 停止:
- 能正确 kill 并使用 `source /etc/profile && ./run.sh` 拉起,日志记录 PID。
5. 当 6060 未监听:
- 能启动 malan 并在 30 秒内监听成功,否则输出失败原因。
6. 所有执行过程有可追溯日志,且不会静默失败。
---
## 需求规范
代码规范:Docs/PRD/01规范文档/_PRD_规范文档_代码规范.md
问题总结:Docs/PRD/01规范文档/_PRD_问题总结_记录文档.md
方法总结:Docs/PRD/01规范文档/_PRD_方法总结_记录文档.md
文档规范:Docs/PRD/01规范文档/_PRD_规范文档_文档规范.md
测试规范:Docs/PRD/01规范文档/_PRD_规范文档_测试规范.md
\ No newline at end of file
# _PRD_后端服务监测需求文档.md
> 版本:V1.0
> 更新日期:2026-01-27
> 适用范围:预定系统后端服务监测与自愈(容器内服务 + 端口服务)
> 参考脚本:`自动化部署脚本\x86架构\预定系统\定时脚本\monitor_inner_api_services.sh`
---
## 1. 背景与目标
### 1.1 背景
会议预定系统部署后,核心后端服务主要运行在 `ujava2` 容器中。以及宿主机端口 `6060``malan` 服务。
为降低故障恢复人工成本,需要引入定时监测与自动恢复能力。
### 1.2 目标
实现一套可定时执行的服务监测与自愈脚本,具备:
- 容器内关键服务进程监测与拉起
- 平台 API 可用性检查,异常时强制重启关键服务(inner)
- 宿主机 6060 端口监测,未监听时启动 malan
- 全流程日志输出与审计
---
## 2. 总体范围
### 2.1 纳入监测对象
1. **平台 API 可用性**
- URL:`https://服务器实际IP地址/api/system/getVerifyCode`
2. **容器:`ujava2` 内部服务进程**
- inner
3. **宿主机 6060 端口及 malan 服务**
- 端口:6060
- 目录:`/var/www/malan`
- 启动命令:`./malan`
### 2.2 不在本期范围(可扩展)
- 指标型监控(CPU/内存/磁盘阈值与告警)
- 日志关键字检索与告警
- 统一告警通道(钉钉/邮件/短信)
- 容器资源限制/扩容策略
---
## 3. 术语说明
- **服务 key**:脚本内部用于标识服务的字符串,如 `meeting2.0`
- **关键服务**:inner(平台 API 异常时强制重启)
- **时间戳**:统一格式 `YYYY-MM-DD HH:MM:SS`
---
## 4. 功能需求
### 4.1 日志与审计
#### 4.1.1 日志文件
- 主日志:`/var/log/monitor-inner-api-services.log`
#### 4.1.2 日志格式
每行必须包含:
- 时间戳:`timestamp()`
- 级别/动作标识:`[START] [STOP] [RUNNING] [STOPPED] [SUCCESS] [FAILED] [WARNING] [ERROR] [SUMMARY]`
- 目标对象:服务 key / 容器名 / 端口
示例:
- `2026-01-27 10:00:00 [RUNNING] gateway (PID: 1234)`
- `2026-01-27 10:00:10 [WARNING] 检测到 4 个服务停止,将重启unacos2容器`
---
### 4.2 平台 API 可用性检查(前置检查)
#### 4.2.1 检查逻辑
请求:
- `GET https://服务器实际IP地址/api/system/getVerifyCode`
- `curl -k -m 10`
判定:
- HTTP 状态码必须为 `200`
- 响应内容必须包含:`"操作成功"``code:200`(允许空格)
#### 4.2.2 处理策略
- 若 API 检查失败:触发 **强制重启内部服务**(见 4.3)
- API 正常:继续后续检查流程
---
### 4.3 容器 ujava2 内部服务监测与自愈
#### 4.3.1 服务清单
| 服务key | jar标识/定位 | 启动脚本 |
| --- | --- | --- |
| meeting2.0 | `ubains-meeting-inner-api` | `/var/www/java/api/java-meeting/java-meeting2.0/run.sh` |
> 注:meeting2.0/3.0 通过 ps 组合条件避免误匹配(脚本内为特判逻辑)。
#### 4.3.2 运行状态判定
判断1:
- 获取 PID:通过 `docker exec ujava2` 在容器内 `ps aux | grep` 定位
- 判定运行:PID 非空 且 `ps -p $pid` 成功
判断2:
- code接口调用:通过curl -v https:/服务器实际IP地址/api/system/getVerifyCode
#### 4.3.3 自愈动作:run.sh
- 启动:在容器内执行:
- `cd /var/www/java/api/java-meeting/java-meeting2.0/`
- `run.sh`
- 等待启动:超时 30 秒
- 成功:输出 `[SUCCESS] service_key (PID: xxx)`
- 失败:输出 `[FAILED] service_key 启动超时`
#### 4.3.4 服务检查:check_services
- 输出本轮检查开始标识:`===== timestamp 服务状态检查 =====`
- 遍历全部服务输出 RUNNING/STOPPED
- 统计 STOPPED 数量 problems
- 调用 `restart_unacos_if_needed problems`
- 返回 problems 作为流程判断依据
---
### 4.4 宿主机 6060 端口与 malan 监测与启动
#### 4.4.1 6060端口检查
端口监听判定满足任一:
- `netstat -tuln | grep ':6060 '`
- `ss -tuln | grep ':6060 '`
- `lsof -i:6060`
#### 4.4.2 启动 malan
- 目录:`/var/www/malan`
- 启动命令:`bash -c "source /etc/profile && ./malan" &`
- 等待端口就绪 30 秒
- 成功:记录 `6060端口已监听`
- 失败:记录 `启动超时,6060端口未监听`
---
## 5. 主流程(顺序要求)
脚本主流程必须按以下顺序执行:
1. **平台 API 检查**
- 若失败 → `restart_critical_services`
2. **容器内服务检查**
- `check_services`
- 若返回非 0 → `restart_problem_services`
3. **6060 端口检查**
- 若未监听 → `start_malan_service`
最后输出:
- `===== timestamp 操作完成 =====`
---
## 6. 配置与可变项
| 配置项 | 默认/当前值 | 说明 |
| --- | --- | --- |
| ujava2容器名 | `ujava2` | 容器内服务执行目标 |
| 平台 API URL | `https://服务器实际IP地址/api/system/getVerifyCode` | 用于判断平台核心可用性 |
| malan 目录 | `/var/www/malan` | 6060端口服务 |
| 服务启动等待 | 30s | start_service/restart_extapi/malan 统一超时 |
---
## 7. 异常处理与容错要求
1. 任何一步失败必须写日志(含原因/路径/命令关键点)。
2. `run.sh` 不存在必须明确提示(各服务)。
3. 重启 unacos 成功后必须等待 30 秒再继续(避免依赖未就绪)。
4. 端口检测必须兼容不同系统命令(netstat/ss/lsof 任一存在即可)。
---
## 8. 交付物
1. 定时脚本:
- `monitor_inner_api_services.sh`
2. 日志文件输出:
- `/var/log/monitor-inner-api-services.log`
3. 使用说明:
- 需要通过 crontab 或 systemd timer 定时执行(频率由运维决定,如每 1~5 分钟一次)。
---
## 9. 验收标准
1. 当任一容器内服务停止时:
- 日志出现 `[STOPPED]` 与后续 `[START]/[SUCCESS]`,服务恢复运行。
2. 当 6060 未监听:
- 能启动 malan 并在 30 秒内监听成功,否则输出失败原因。
3. 所有执行过程有可追溯日志,且不会静默失败。
---
## 需求规范
代码规范:Docs/PRD/01规范文档/_PRD_规范文档_代码规范.md
问题总结:Docs/PRD/01规范文档/_PRD_问题总结_记录文档.md
方法总结:Docs/PRD/01规范文档/_PRD_方法总结_记录文档.md
文档规范:Docs/PRD/01规范文档/_PRD_规范文档_文档规范.md
测试规范:Docs/PRD/01规范文档/_PRD_规范文档_测试规范.md
\ No newline at end of file
#!/bin/bash
LOG_FILE="/data/logs/ujava2-service-manager.log"
unacos_LOG="/data/logs/unacos_restart.log"
timestamp() {
date "+%Y-%m-%d %H:%M:%S"
}
declare -A SERVICE_CMD_MAP=(
["auth"]="ubains-auth.jar"
["gateway"]="ubains-gateway.jar"
["system"]="ubains-modules-system.jar"
["meeting2.0"]="java-meeting2.0/ubains-meeting-inner-api-1.0-SNAPSHOT.jar"
["meeting3.0"]="java-meeting3.0/ubains-meeting-inner-api-1.0-SNAPSHOT.jar"
["mqtt"]="ubains-meeting-mqtt-1.0-SNAPSHOT.jar"
["quartz"]="ubains-meeting-quartz-1.0-SNAPSHOT.jar"
["message"]="ubains-meeting-message-scheduling-1.0-SNAPSHOT.jar"
)
declare -A SERVICE_SCRIPT_MAP=(
["auth"]="/var/www/java/api/auth/auth-sso-auth/run.sh"
["gateway"]="/var/www/java/api/auth/auth-sso-gatway/run.sh"
["system"]="/var/www/java/api/auth/auth-sso-system/run.sh"
["meeting2.0"]="/var/www/java/api/java-meeting/java-meeting2.0/run.sh"
["meeting3.0"]="/var/www/java/api/java-meeting/java-meeting3.0/run.sh"
["mqtt"]="/var/www/java/api/java-meeting/java-mqtt/run.sh"
["quartz"]="/var/www/java/api/java-meeting/java-quartz/run.sh"
["message"]="/var/www/java/api/java-meeting/java-message-scheduling/run.sh"
)
# 平台API检查函数(通用方法,不依赖jq)
check_platform_api() {
local api_url="https://192.168.5.44/platform/api/code"
local http_code
local response
# 获取HTTP状态码和响应内容
response=$(curl -s -k -m 10 -w "\n%{http_code}" "$api_url" 2>/dev/null)
http_code=$(echo "$response" | tail -1)
response=$(echo "$response" | sed '$d')
# 首先检查HTTP状态码
if [ "$http_code" != "200" ]; then
echo "$(timestamp) [ERROR] 平台API检查失败: HTTP状态码 $http_code" | tee -a "$LOG_FILE"
return 1
fi
# 检查响应是否为空
if [ -z "$response" ]; then
echo "$(timestamp) [ERROR] 平台API检查失败: 响应为空" | tee -a "$LOG_FILE"
return 1
fi
# 使用grep检查JSON响应中的关键字段(所有Linux系统都有grep)
# 检查是否包含 "操作成功" 和 "code":200 或 "code": 200
if echo "$response" | grep -q '"操作成功"' && \
echo "$response" | grep -qE '"code"[[:space:]]*:[[:space:]]*200'; then
echo "$(timestamp) [INFO] 平台API检查正常" | tee -a "$LOG_FILE"
return 0
else
echo "$(timestamp) [ERROR] 平台API检查失败: ${response:0:200}..." | tee -a "$LOG_FILE"
return 1
fi
}
# 修改后的重启关键服务函数
restart_critical_services() {
echo "$(timestamp) [WARNING] 开始强制重启gateway、auth、system服务" | tee -a "$LOG_FILE"
local services=("gateway" "auth" "system")
local restarted=0
for service in "${services[@]}"; do
# 无论服务是否运行,都先停止再启动
stop_service "$service"
if start_service "$service"; then
((restarted++))
fi
done
echo "$(timestamp) [SUMMARY] 已强制重启 $restarted 个关键服务" | tee -a "$LOG_FILE"
}
# 原有unacos健康检查函数
check_unacos_health() {
# 检查unacos容器是否运行
if ! docker inspect unacos2 &>/dev/null; then
echo "$(timestamp) [ERROR] unacos2容器未找到" | tee -a "$unacos_LOG"
return 1
fi
# 检查unacos容器是否处于运行状态
if [ "$(docker inspect -f '{{.State.Status}}' unacos2)" != "running" ]; then
echo "$(timestamp) [ERROR] unacos2容器未运行" | tee -a "$unacos_LOG"
return 1
fi
# 简单检查unacos API是否可访问
if ! curl -s -m 5 "http://localhost:8848/nacos/" &>/dev/null; then
echo "$(timestamp) [WARNING] unacos2服务不可访问" | tee -a "$unacos_LOG"
return 1
fi
return 0
}
get_service_pid() {
local service_key="$1"
local jar_path="${SERVICE_CMD_MAP[$service_key]}"
# 通过工作目录和jar文件名组合查找
case "$service_key" in
"meeting2.0")
docker exec ujava2 sh -c "ps aux | grep '[j]ava' | grep -F 'ubains-meeting-inner-api' | grep -F 'java-meeting2.0/config' | grep -v 'java-meeting3.0' | awk '{print \$2}' | head -1"
;;
"meeting3.0")
docker exec ujava2 sh -c "ps aux | grep '[j]ava' | grep -F 'ubains-meeting-inner-api' | grep -F 'java-meeting3.0//config' | awk '{print \$2}' | head -1"
;;
*)
docker exec ujava2 sh -c "ps aux | grep -F '$jar_path' | grep -v grep | awk '{print \$2}' | head -1"
;;
esac
}
is_service_running() {
local pid=$(get_service_pid "$1")
[ -n "$pid" ] && docker exec ujava2 sh -c "ps -p $pid >/dev/null 2>&1"
}
start_service() {
local service_key="$1"
echo "$(timestamp) [START] $service_key" | tee -a "$LOG_FILE"
stop_service "$service_key"
docker exec -d ujava2 bash -c "nohup ${SERVICE_SCRIPT_MAP[$service_key]} > /var/log/${service_key}.log 2>&1 & echo \$! > /tmp/${service_key}.pid"
local timeout=30
while ((timeout-- > 0)); do
if is_service_running "$service_key"; then
local pid=$(get_service_pid "$service_key")
echo "$(timestamp) [SUCCESS] $service_key (PID: $pid)" | tee -a "$LOG_FILE"
return 0
fi
sleep 1
done
echo "$(timestamp) [FAILED] $service_key 启动超时" | tee -a "$LOG_FILE"
return 1
}
stop_service() {
local service_key="$1"
local pid=$(get_service_pid "$service_key")
[ -z "$pid" ] && return 0
echo "$(timestamp) [STOP] $service_key (PID: $pid)" | tee -a "$LOG_FILE"
docker exec ujava2 sh -c "kill $pid && sleep 1 || kill -9 $pid"
sleep 2
}
restart_unacos_if_needed() {
local stopped_count=$1
# 先检查unacos健康状态
if ! check_unacos_health; then
echo "$(timestamp) [WARNING] unacos2服务异常,将尝试重启" | tee -a "$unacos_LOG"
docker restart unacos2 >> "$unacos_LOG" 2>&1
if [ $? -eq 0 ]; then
echo "$(timestamp) [SUCCESS] unacos2容器重启成功" | tee -a "$unacos_LOG"
sleep 30
else
echo "$(timestamp) [ERROR] unacos2容器重启失败" | tee -a "$unacos_LOG"
fi
return
fi
# 原有逻辑:当停止的服务超过3个时重启unacos
if [ "$stopped_count" -gt 3 ]; then
echo "$(timestamp) [WARNING] 检测到 $stopped_count 个服务停止,将重启unacos2容器" | tee -a "$unacos_LOG"
docker restart unacos2 >> "$unacos_LOG" 2>&1
if [ $? -eq 0 ]; then
echo "$(timestamp) [SUCCESS] unacos2容器重启成功" | tee -a "$unacos_LOG"
sleep 30
else
echo "$(timestamp) [ERROR] unacos2容器重启失败" | tee -a "$unacos_LOG"
fi
fi
}
check_services() {
local problems=0
echo "===== $(timestamp) 服务状态检查 =====" | tee -a "$LOG_FILE"
# 首先检查unacos状态
if ! check_unacos_health; then
echo "$(timestamp) [WARNING] unacos2服务异常,可能会影响其他服务" | tee -a "$LOG_FILE"
fi
for service_key in "${!SERVICE_CMD_MAP[@]}"; do
if is_service_running "$service_key"; then
local pid=$(get_service_pid "$service_key")
echo "$(timestamp) [RUNNING] $service_key (PID: $pid)" | tee -a "$LOG_FILE"
else
echo "$(timestamp) [STOPPED] $service_key" | tee -a "$LOG_FILE"
((problems++))
fi
done
restart_unacos_if_needed $problems
return $problems
}
restart_problem_services() {
local restarted=0
echo "===== $(timestamp) 服务恢复启动 =====" | tee -a "$LOG_FILE"
# 检查unacos是否正常,如果不正常先重启unacos
if ! check_unacos_health; then
echo "$(timestamp) [WARNING] unacos2服务异常,将先重启unacos2" | tee -a "$LOG_FILE"
docker restart unacos2 >> "$unacos_LOG" 2>&1
sleep 30
fi
for service_key in "${!SERVICE_CMD_MAP[@]}"; do
if ! is_service_running "$service_key"; then
if start_service "$service_key"; then
((restarted++))
fi
fi
done
echo "$(timestamp) [SUMMARY] 已尝试重启 $restarted 个服务" | tee -a "$LOG_FILE"
}
# ========== 宿主机对外服务监测函数(新增) ==========
# 获取宿主机对外服务的PID
get_host_extapi_pid() {
ps aux | grep -F 'ubains-meeting-api-1.0-SNAPSHOT.jar' | grep -v grep | awk '{print $2}' | head -1
}
# 检查宿主机对外服务是否运行
is_host_extapi_running() {
local pid=$(get_host_extapi_pid)
[ -n "$pid" ] && ps -p "$pid" >/dev/null 2>&1
}
# 检查宿主机对外服务状态
check_host_extapi_service() {
local service_name="extapi"
local service_path="/data/services/api/java-meeting/java-meeting-extapi"
local jar_file="ubains-meeting-api-1.0-SNAPSHOT.jar"
echo "===== $(timestamp) 宿主机对外服务状态检查 =====" | tee -a "$LOG_FILE"
if is_host_extapi_running; then
local pid=$(get_host_extapi_pid)
echo "$(timestamp) [RUNNING] $service_name (PID: $pid)" | tee -a "$LOG_FILE"
return 0
else
echo "$(timestamp) [STOPPED] $service_name" | tee -a "$LOG_FILE"
return 1
fi
}
# 重启宿主机对外服务
restart_host_extapi_service() {
local service_name="extapi"
local service_path="/data/services/api/java-meeting/java-meeting-extapi"
local jar_file="ubains-meeting-api-1.0-SNAPSHOT.jar"
local run_script="${service_path}/run.sh"
echo "$(timestamp) [START] 宿主机服务 $service_name" | tee -a "$LOG_FILE"
# 停止服务
local pid=$(get_host_extapi_pid)
if [ -n "$pid" ]; then
echo "$(timestamp) [STOP] $service_name (PID: $pid)" | tee -a "$LOG_FILE"
kill "$pid" 2>/dev/null && sleep 1 || kill -9 "$pid" 2>/dev/null
sleep 2
fi
# 检查启动脚本是否存在
if [ ! -f "$run_script" ]; then
echo "$(timestamp) [ERROR] 启动脚本不存在: $run_script" | tee -a "$LOG_FILE"
return 1
fi
# 启动服务
cd "$service_path" || {
echo "$(timestamp) [ERROR] 无法进入服务目录: $service_path" | tee -a "$LOG_FILE"
return 1
}
# 加载 /etc/profile 中的环境变量(包括 Java 环境变量),然后执行 run.sh
# 使用 bash -c 确保环境变量在同一 shell 中生效并传递到 run.sh
bash -c "source /etc/profile && ./run.sh" &
local start_pid=$!
# 等待服务启动
local timeout=30
while ((timeout-- > 0)); do
if is_host_extapi_running; then
local pid=$(get_host_extapi_pid)
echo "$(timestamp) [SUCCESS] $service_name (PID: $pid)" | tee -a "$LOG_FILE"
return 0
fi
sleep 1
done
echo "$(timestamp) [FAILED] $service_name 启动超时" | tee -a "$LOG_FILE"
return 1
}
# ========== 6060端口监测函数(新增) ==========
# 检查6060端口是否在监听
check_port_6060() {
if netstat -tuln 2>/dev/null | grep -q ':6060 ' || \
ss -tuln 2>/dev/null | grep -q ':6060 ' || \
lsof -i:6060 >/dev/null 2>&1; then
return 0 # 端口正在监听
else
return 1 # 端口未监听
fi
}
# 启动malan服务
start_malan_service() {
local malan_path="/data/middleware/monitor"
local service_name="malan"
echo "$(timestamp) [START] 启动 $service_name 服务" | tee -a "$LOG_FILE"
# 检查目录是否存在
if [ ! -d "$malan_path" ]; then
echo "$(timestamp) [ERROR] malan目录不存在: $malan_path" | tee -a "$LOG_FILE"
return 1
fi
# 进入目录并启动malan(后台运行)
cd "$malan_path" || {
echo "$(timestamp) [ERROR] 无法进入目录: $malan_path" | tee -a "$LOG_FILE"
return 1
}
# 加载环境变量,然后启动malan
bash -c "source /etc/profile && ./malan" &
local start_pid=$!
# 等待端口启动
local timeout=30
local waited=0
while ((timeout-- > 0)); do
if check_port_6060; then
echo "$(timestamp) [SUCCESS] $service_name 启动成功,6060端口已监听" | tee -a "$LOG_FILE"
return 0
fi
((waited++))
sleep 1
done
echo "$(timestamp) [FAILED] $service_name 启动超时,6060端口未监听" | tee -a "$LOG_FILE"
return 1
}
# 检查并启动malan服务(如果需要)
check_and_start_malan() {
echo "===== $(timestamp) 6060端口状态检查 =====" | tee -a "$LOG_FILE"
if check_port_6060; then
echo "$(timestamp) [INFO] 6060端口正在监听" | tee -a "$LOG_FILE"
return 0
else
echo "$(timestamp) [WARNING] 6060端口未监听,将启动malan服务" | tee -a "$LOG_FILE"
start_malan_service
return $?
fi
}
# 主流程
# 先检查平台API
if ! check_platform_api; then
restart_critical_services
fi
# 原有服务检查逻辑
check_services || restart_problem_services
# 宿主机对外服务检查(新增)
if ! check_host_extapi_service; then
restart_host_extapi_service
fi
# 6060端口监测(新增)
check_and_start_malan
echo "===== $(timestamp) 操作完成 =====" | tee -a "$LOG_FILE"
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论