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

feat(skills): X86集群监控钉钉摘要重构、新增ARM节点监控脚本、QLV10定时任务调整

- report_analyzer.py: 报告路径改绝对路径(__file__)避免依赖运行目录;节点匹配正则适配新报告格式(含角色列);钉钉摘要重构为ARM风格六大节列表格式
- dingtalk_notifier.py: 防重发标记改用绝对路径
- config.json: 启用钉钉通知(enabled: true)
- 新增ARM集群节点监控脚本(arm_monitor_*/check_*/monitor_node4/monitor_slave2_91)及结果JSON
- X86-QLV10-XTYBS: 定时任务22:00→23:00,解决与TX任务串行阻塞问题
- CreateCMD: 更新claude工作路径和nvm4w路径
Co-Authored-By: 's avatarClaude <noreply@anthropic.com>
上级 1fc095d1
{
"ip": "192.168.9.90",
"role": "slave1",
"status": "warning",
"cpu": "7.5%",
"memory": "89.6%",
"disk": "/data 33% (25G/79G), / 33% (2.6G/7.8G)",
"load": "1.72, 4.96, 4.77",
"uptime": "5 days, 17:49",
"containers": {
"total": 9,
"running": 9,
"abnormal": [],
"details": "utracker(Up 4d), redis-slave-1(Up 5d), redis-sentinel-2(Up 5d), unacos(Up 17h), uemqx(Up 5d), utengine(Up 5d), paperless(Up 5d), ujava2(Up 5d), umysql(Up 5d)"
},
"middleware": {
"mysql": "ok",
"redis": "ok",
"emqx": "ok",
"nacos": "ok"
},
"java_services": 9,
"log_errors": 0,
"alerts": [
"内存使用率89.6%(含缓存),可用内存仅1661MB/15948MB(10.4%),接近85%告警阈值"
],
"summary": "slave1节点整体运行正常,9个容器全部Running,4项中间件(MySQL/Redis/EMQX/Nacos)功能验证通过,CPU负载低(7.5%),日志无ERROR。但内存使用率89.6%已达WARNING级别(>85%),可用内存仅1.6GB,需关注内存消耗趋势。unacos容器17小时前重启过,建议排查重启原因。"
}
\ No newline at end of file
@echo off @echo off
cd /d E:\github\ubains-module-test\develop cd /d C:\PycharmData\ubains-module-test\develop
E:\nodejs\claude.cmd --permission-mode bypassPermissions C:\nvm4w\nodejs\claude.cmd --permission-mode bypassPermissions
import paramiko
import json
import re
import time
HOST = '192.168.9.91'
PORT = 22
USER = 'openkylin'
PASS = 'Ubains@123'
def ssh_exec(ssh, cmd, timeout=30):
try:
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=timeout)
out = stdout.read().decode('utf-8', errors='replace').strip()
err = stderr.read().decode('utf-8', errors='replace').strip()
return out, err
except Exception as e:
return '', str(e)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(HOST, port=PORT, username=USER, password=PASS, timeout=15)
result = {
'ip': HOST,
'role': 'slave2',
'status': 'normal',
'cpu': '',
'memory': '',
'disk': '',
'load': '',
'uptime': '',
'containers': {'total': 0, 'running': 0, 'abnormal': [], 'details': ''},
'middleware': {'mysql': 'skip', 'redis': 'skip', 'emqx': 'skip', 'nacos': 'skip'},
'java_services': 0,
'log_errors': 0,
'alerts': [],
'summary': ''
}
# Use C locale to avoid Chinese encoding issues
LC = 'export LC_ALL=C LANG=C; '
# 1. CPU
out, err = ssh_exec(ssh, LC + 'top -bn1|grep Cpu')
print('CPU raw:', repr(out))
cpu_usage = 0
if out:
m = re.search(r'(\d+\.\d+)\s+id', out)
if m:
cpu_usage = round(100 - float(m.group(1)), 1)
result['cpu'] = str(cpu_usage) + '%'
# 2. Memory - use C locale
out, err = ssh_exec(ssh, LC + 'free -m')
print('MEM raw:', repr(out))
mem_usage = 0
mem_total_mb = 0
mem_used_mb = 0
mem_avail_mb = 0
if out:
lines = out.split('\n')
for line in lines:
if line.startswith('Mem:'):
parts = line.split()
mem_total_mb = int(parts[1])
mem_used_mb = int(parts[2])
# available is the last column in modern free
mem_avail_mb = int(parts[6]) if len(parts) > 6 else int(parts[3])
mem_usage = round((1 - mem_avail_mb / mem_total_mb) * 100, 1)
break
print(f'MEM total:{mem_total_mb} used:{mem_used_mb} avail:{mem_avail_mb} usage:{mem_usage}%')
result['memory'] = str(mem_usage) + '%'
# 3. Disk
out, err = ssh_exec(ssh, LC + 'df -h')
print('DISK raw:', repr(out))
disk_info = []
disk_alerts = []
if out:
lines = out.split('\n')
for line in lines[1:]:
parts = line.split()
if len(parts) >= 6 and parts[0].startswith('/dev/'):
mount = parts[5]
usage = parts[4]
size = parts[1]
disk_info.append(f'{mount}:{usage}({size})')
usage_pct = usage.replace('%', '')
try:
if int(usage_pct) > 85:
disk_alerts.append(f'Disk {mount} usage {usage_pct}% > 85%')
except:
pass
result['disk'] = '; '.join(disk_info) if disk_info else 'N/A'
# 4. Load and Uptime
out, err = ssh_exec(ssh, LC + 'uptime')
print('UPTIME raw:', repr(out))
if out:
m = re.search(r'load average:\s*([\d.]+),\s*([\d.]+),\s*([\d.]+)', out)
if m:
result['load'] = f'{m.group(1)},{m.group(2)},{m.group(3)}'
m2 = re.search(r'up\s+(.+?),\s*\d+\s+user', out)
if m2:
result['uptime'] = m2.group(1).strip()
# 5. Containers
out, err = ssh_exec(ssh, 'sudo docker ps -a --format "{{.Names}}\t{{.Status}}"', timeout=30)
print('DOCKER PS raw:', repr(out))
containers = []
running = 0
abnormal = []
if out:
for line in out.split('\n'):
if not line.strip():
continue
parts = line.split('\t')
if len(parts) >= 2:
name = parts[0]
status = parts[1]
containers.append(f'{name}({status})')
if 'Up' in status:
running += 1
else:
abnormal.append(name)
out2, err2 = ssh_exec(ssh, 'sudo docker stats --no-stream', timeout=30)
print('DOCKER STATS raw:', repr(out2))
# Check high CPU containers
high_cpu_containers = []
if out2:
for line in out2.split('\n')[1:]:
if not line.strip():
continue
parts = line.split()
if len(parts) >= 3:
name = parts[1]
cpu_str = parts[2]
try:
cpu_val = float(cpu_str.replace('%', ''))
if cpu_val > 100:
high_cpu_containers.append(f'{name}:{cpu_str}')
except:
pass
total = len(containers)
result['containers']['total'] = total
result['containers']['running'] = running
result['containers']['abnormal'] = abnormal
result['containers']['details'] = f'Total:{total}, Running:{running}, Stopped:{total-running}'
if high_cpu_containers:
result['containers']['details'] += f', HighCPU:{",".join(high_cpu_containers)}'
# 6. Middleware
# MySQL
out, err = ssh_exec(ssh, "sudo docker exec umysql mysql -uroot -p'dNrprU&2S' -e 'SELECT 1;'", timeout=15)
print('MySQL raw:', repr(out), repr(err))
if '1' in out and 'ERROR' not in err and 'Access denied' not in err:
result['middleware']['mysql'] = 'ok'
else:
result['middleware']['mysql'] = 'fail'
# Redis
out, err = ssh_exec(ssh, "sudo docker exec redis-slave-2 redis-cli -a 'dNrprU&2S' ping", timeout=15)
print('Redis raw:', repr(out), repr(err))
if 'PONG' in out:
result['middleware']['redis'] = 'ok'
else:
result['middleware']['redis'] = 'fail'
# EMQX - check both "started" and "running"
out, err = ssh_exec(ssh, 'sudo docker exec uemqx emqx_ctl status', timeout=15)
print('EMQX raw:', repr(out), repr(err))
if 'started' in out.lower() or 'running' in out.lower():
result['middleware']['emqx'] = 'ok'
else:
result['middleware']['emqx'] = 'fail'
# Nacos
out, err = ssh_exec(ssh, 'curl -s -o /dev/null -w "%{http_code}" http://localhost:8848/nacos/', timeout=15)
print('Nacos raw:', repr(out))
if out in ['200', '302']:
result['middleware']['nacos'] = 'ok'
elif out:
result['middleware']['nacos'] = 'fail'
# 7. Java processes
out, err = ssh_exec(ssh, 'ps aux|grep java|grep -v grep|wc -l')
print('Java count raw:', repr(out))
try:
result['java_services'] = int(out.strip())
except:
result['java_services'] = 0
# Check for high CPU java processes
out, err = ssh_exec(ssh, LC + 'ps aux|grep java|grep -v grep')
print('Java processes:', repr(out))
high_cpu_java = []
if out:
for line in out.split('\n'):
if not line.strip():
continue
parts = line.split()
if len(parts) >= 3:
try:
cpu_val = float(parts[2])
if cpu_val > 100:
# extract jar name
jar_match = re.search(r'(\S+\.jar)', line)
jar_name = jar_match.group(1) if jar_match else parts[-1]
high_cpu_java.append(f'{jar_name}:{cpu_val}%')
except:
pass
# 8. Log errors
out, err = ssh_exec(ssh, 'find /data/services -name "*.log" -mmin -120 -exec grep -l "ERROR\\|Exception" {} \\; 2>/dev/null|wc -l', timeout=30)
print('LogError raw:', repr(out))
try:
result['log_errors'] = int(out.strip())
except:
result['log_errors'] = 0
# Determine status
alerts = []
if cpu_usage > 80:
alerts.append(f'CPU usage {cpu_usage}% > 80%')
if mem_usage > 85:
alerts.append(f'Memory usage {mem_usage}% > 85%')
result['status'] = 'critical'
elif mem_usage > 70:
alerts.append(f'Memory usage {mem_usage}% > 70%')
if result['status'] != 'critical':
result['status'] = 'warning'
if abnormal:
alerts.append(f'Stopped containers: {abnormal}')
if result['status'] == 'normal':
result['status'] = 'warning'
if disk_alerts:
alerts.extend(disk_alerts)
if result['status'] == 'normal':
result['status'] = 'warning'
if high_cpu_containers:
alerts.append(f'High container CPU: {",".join(high_cpu_containers)}')
if high_cpu_java:
alerts.append(f'High CPU Java: {",".join(high_cpu_java)}')
if result['status'] == 'normal':
result['status'] = 'warning'
# Load check
if result['load']:
loads = result['load'].split(',')
try:
load1 = float(loads[0])
ncpu_out, _ = ssh_exec(ssh, 'nproc')
ncpu = int(ncpu_out.strip()) if ncpu_out.strip() else 4
if load1 > ncpu * 2:
alerts.append(f'Load {load1} very high (cores:{ncpu})')
if result['status'] == 'normal':
result['status'] = 'warning'
except:
pass
# Log errors check
if result['log_errors'] > 0:
alerts.append(f'{result["log_errors"]} log files with ERROR/Exception in last 2h')
result['alerts'] = alerts
# Summary
mw_status = '/'.join([f'{k}:{v}' for k, v in result['middleware'].items()])
if result['status'] == 'critical':
result['summary'] = f'CRITICAL: CPU:{cpu_usage}%, MEM:{mem_usage}%, Load:{result["load"]}, Alerts:{len(alerts)}'
elif result['status'] == 'warning':
result['summary'] = f'WARNING: CPU:{cpu_usage}%, MEM:{mem_usage}%, Load:{result["load"]}, Containers:{running}/{total}, MW:{mw_status}'
else:
result['summary'] = f'OK: CPU:{cpu_usage}%, MEM:{mem_usage}%, Load:{result["load"]}, Containers:{running}/{total} running'
ssh.close()
print(json.dumps(result, ensure_ascii=False))
import paramiko
import json
import re
ip = '192.168.9.90'
port = 22
user = 'openkylin'
password = 'Ubains@123'
def ssh_exec(client, cmd, timeout=30):
try:
stdin, stdout, stderr = client.exec_command(cmd, timeout=timeout)
out = stdout.read().decode('utf-8', errors='replace').strip()
err = stderr.read().decode('utf-8', errors='replace').strip()
return out, err
except Exception as e:
return '', str(e)
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
result = {
'ip': ip,
'role': 'slave1',
'status': 'normal',
'cpu': '',
'memory': '',
'disk': '',
'load': '',
'uptime': '',
'containers': {'total': 0, 'running': 0, 'abnormal': [], 'details': ''},
'middleware': {'mysql': 'skip', 'redis': 'skip', 'emqx': 'skip', 'nacos': 'skip'},
'java_services': 0,
'log_errors': 0,
'alerts': [],
'summary': ''
}
try:
client.connect(ip, port=port, username=user, password=password, timeout=10)
# 1. CPU
out, err = ssh_exec(client, 'top -bn1|grep Cpu')
cpu_match = re.search(r'(\S+)\s*id', out)
if cpu_match:
idle = float(cpu_match.group(1))
result['cpu'] = round(100 - idle, 1)
else:
result['cpu'] = out if out else 'N/A'
# 2. Memory
out, err = ssh_exec(client, 'free -m')
lines = out.split('\n')
if len(lines) >= 2:
mem_parts = lines[1].split()
if len(mem_parts) >= 3:
total = int(mem_parts[1])
used = int(mem_parts[2])
result['memory'] = round(used / total * 100, 1) if total > 0 else 0
# 3. Disk
out, err = ssh_exec(client, 'df -h')
disk_lines = []
for line in out.split('\n')[1:]:
parts = line.split()
if len(parts) >= 6 and parts[0].startswith('/dev/'):
disk_lines.append({
'mount': parts[5],
'usage': parts[4],
'total': parts[1],
'used': parts[2],
'avail': parts[3]
})
result['disk'] = disk_lines
# 4. Load & Uptime
out, err = ssh_exec(client, 'uptime')
load_match = re.search(r'load average:\s*([\d.]+),\s*([\d.]+),\s*([\d.]+)', out)
if load_match:
result['load'] = f"{load_match.group(1)},{load_match.group(2)},{load_match.group(3)}"
up_match = re.search(r'up\s+([^,]+)', out)
if up_match:
result['uptime'] = up_match.group(1).strip()
# 5. Containers
out, err = ssh_exec(client, 'sudo docker ps -a --format "{{.Names}}\t{{.Status}}"', timeout=30)
containers = []
abnormal = []
running = 0
if out:
for line in out.split('\n'):
if not line.strip():
continue
parts = line.split('\t')
if len(parts) >= 2:
name = parts[0]
status = parts[1]
containers.append({'name': name, 'status': status})
if 'Up' in status:
running += 1
else:
abnormal.append(name)
total = len(containers)
result['containers']['total'] = total
result['containers']['running'] = running
result['containers']['abnormal'] = abnormal
result['containers']['details'] = f"total:{total}, running:{running}, stopped:{total-running}"
# Docker stats
out_stats, err_stats = ssh_exec(client, 'sudo docker stats --no-stream', timeout=30)
if out_stats:
result['containers']['stats'] = out_stats
# 6. Middleware
# MySQL
out, err = ssh_exec(client, "sudo docker exec umysql mysql -uroot -p'dNrprU&2S' -e 'SELECT 1;'", timeout=15)
if '1' in out and 'ERROR' not in err:
result['middleware']['mysql'] = 'ok'
elif 'ERROR' in err or 'error' in err.lower():
result['middleware']['mysql'] = 'fail'
else:
result['middleware']['mysql'] = 'ok' if out else 'fail'
# Redis
out, err = ssh_exec(client, "sudo docker exec redis-slave-1 redis-cli -a 'dNrprU&2S' ping", timeout=15)
if 'PONG' in out:
result['middleware']['redis'] = 'ok'
else:
result['middleware']['redis'] = 'fail'
# EMQX
out, err = ssh_exec(client, 'sudo docker exec uemqx emqx_ctl status', timeout=15)
if 'running' in out.lower() or 'is_running' in out.lower():
result['middleware']['emqx'] = 'ok'
else:
result['middleware']['emqx'] = 'fail' if out else 'skip'
# Nacos
out, err = ssh_exec(client, 'curl -s -o /dev/null -w "%{http_code}" http://localhost:8848/nacos/', timeout=15)
if out.strip() in ['200', '302']:
result['middleware']['nacos'] = 'ok'
elif out.strip():
result['middleware']['nacos'] = 'fail'
else:
result['middleware']['nacos'] = 'skip'
# 7. Java processes
out, err = ssh_exec(client, 'ps aux|grep java|grep -v grep|wc -l')
try:
result['java_services'] = int(out.strip())
except:
result['java_services'] = 0
# 8. Log errors
out, err = ssh_exec(client, 'find /data/services -name "*.log" -mmin -120 -exec grep -l "ERROR\\|Exception" {} \\; 2>/dev/null|wc -l', timeout=30)
try:
result['log_errors'] = int(out.strip())
except:
result['log_errors'] = 0
# Determine status
alerts = []
cpu_val = result['cpu'] if isinstance(result['cpu'], (int, float)) else 0
mem_val = result['memory'] if isinstance(result['memory'], (int, float)) else 0
if cpu_val > 90:
alerts.append(f'CPU usage high: {cpu_val}%')
if mem_val > 90:
alerts.append(f'Memory usage high: {mem_val}%')
if abnormal:
alerts.append(f'Abnormal containers: {abnormal}')
# Check disk usage
for d in disk_lines:
usage_str = d.get('usage', '0%').replace('%', '')
try:
if float(usage_str) > 90:
alerts.append(f"Disk high: {d['mount']} {d['usage']}")
except:
pass
# Check middleware failures
for mw, st in result['middleware'].items():
if st == 'fail':
alerts.append(f'{mw} check failed')
if result['log_errors'] > 0:
alerts.append(f"Log errors found: {result['log_errors']} files")
result['alerts'] = alerts
if any('high' in a or 'fail' in a for a in alerts) or cpu_val > 90 or mem_val > 90:
result['status'] = 'critical'
elif alerts:
result['status'] = 'warning'
else:
result['status'] = 'normal'
# Summary
result['summary'] = f"slave1({ip}): CPU {cpu_val}%, MEM {mem_val}%, containers {running}/{total} running, load {result['load']}"
client.close()
except Exception as e:
result['status'] = 'critical'
result['alerts'].append(f'SSH connection failed: {str(e)}')
result['summary'] = f'slave1({ip}): connection failed - {str(e)}'
print(json.dumps(result, ensure_ascii=False))
import paramiko
import json
import time
host = "192.168.9.89"
port = 22
username = "openkylin"
password = "Ubains@123"
result = {
"ip": host,
"role": "master",
"status": "normal",
"cpu": "N/A",
"memory": "N/A",
"disk": "N/A",
"load": "N/A",
"uptime": "N/A",
"containers": {
"total": 0,
"running": 0,
"abnormal": [],
"details": ""
},
"middleware": {
"mysql": "skip",
"redis": "skip",
"emqx": "skip",
"nacos": "skip"
},
"java_services": [],
"log_errors": 0,
"alerts": [],
"summary": ""
}
try:
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(host, port=port, username=username, password=password, timeout=15)
print(f"[OK] SSH connected to {host}")
except Exception as e:
result["status"] = "critical"
result["summary"] = f"SSH连接失败: {str(e)}"
result["alerts"].append(f"SSH连接失败: {str(e)}")
print(json.dumps(result, ensure_ascii=False, indent=2))
exit(0)
def run_cmd(cmd, timeout=10):
try:
stdin, stdout, stderr = client.exec_command(cmd, timeout=timeout)
out = stdout.read().decode('utf-8', errors='ignore').strip()
err = stderr.read().decode('utf-8', errors='ignore').strip()
return out, err
except Exception as e:
return "", str(e)
# ============ 1. System Resources ============
print("=== Checking System Resources ===")
# CPU
out, _ = run_cmd("top -bn1 | grep 'Cpu(s)' | awk '{print $2}' | cut -d'%' -f1")
if out:
result["cpu"] = f"{out}%"
print(f" CPU: {result['cpu']}")
else:
out2, _ = run_cmd("cat /proc/loadavg")
if out2:
parts = out2.split()
result["cpu"] = f"load: {parts[0]}/{parts[1]}"
print(f" CPU load: {result['cpu']}")
# Memory
out, _ = run_cmd("free -m | awk 'NR==2{printf \"%.1f\", $3*100/$2}'")
if out:
result["memory"] = f"{out}%"
print(f" Memory: {result['memory']}")
# Disk
out, _ = run_cmd("df -h | grep -E '^/' | awk '{print $5, $6}'")
if out:
disk_lines = out.split('\n')
disk_strs = []
for line in disk_lines:
parts = line.strip().split()
if len(parts) >= 2:
disk_strs.append(f"{parts[1]} {parts[0]}")
result["disk"] = ", ".join(disk_strs)
print(f" Disk: {result['disk']}")
# Load
out, _ = run_cmd("uptime | awk -F'load average:' '{print $2}'")
if out:
result["load"] = out.strip()
print(f" Load: {result['load']}")
# Uptime
out, _ = run_cmd("uptime -s")
if out:
result["uptime"] = out.strip()
print(f" Uptime: {result['uptime']}")
# ============ 2. Docker Container Status ============
print("=== Checking Docker Containers ===")
out, err = run_cmd("docker ps -a --format '{{.Names}}\\t{{.Status}}\\t{{.Ports}}' 2>&1", timeout=15)
print(f" Docker raw output length: {len(out)}")
if out and not out.startswith("Cannot connect") and not out.startswith("permission"):
lines = [l for l in out.strip().split('\n') if l.strip()]
result["containers"]["total"] = len(lines)
container_details = []
running_count = 0
for line in lines:
parts = line.split('\t')
if len(parts) >= 2:
name = parts[0]
status = parts[1]
ports = parts[2] if len(parts) > 2 else ""
container_details.append(f"{name}: {status}")
if "Up" in status:
running_count += 1
else:
result["containers"]["abnormal"].append(name)
result["containers"]["running"] = running_count
result["containers"]["details"] = "; ".join(container_details)
print(f" Total: {len(lines)}, Running: {running_count}, Abnormal: {len(result['containers']['abnormal'])}")
if container_details:
for d in container_details:
print(f" - {d}")
else:
# Try with sudo
out2, err2 = run_cmd("sudo docker ps -a --format '{{.Names}}\\t{{.Status}}' 2>&1", timeout=15)
if out2 and not out2.startswith("Cannot") and not out2.startswith("permission") and not out2.startswith("sudo"):
lines = [l for l in out2.strip().split('\n') if l.strip()]
result["containers"]["total"] = len(lines)
container_details = []
running_count = 0
for line in lines:
parts = line.split('\t')
if len(parts) >= 2:
name = parts[0]
status = parts[1]
container_details.append(f"{name}: {status}")
if "Up" in status:
running_count += 1
else:
result["containers"]["abnormal"].append(name)
result["containers"]["running"] = running_count
result["containers"]["details"] = "; ".join(container_details)
print(f" [sudo] Total: {len(lines)}, Running: {running_count}")
for d in container_details:
print(f" - {d}")
else:
print(f" Docker not accessible: {out[:100]} | {err[:100]}")
result["alerts"].append("Docker不可访问")
# Container resource usage
out, _ = run_cmd("docker stats --no-stream --format '{{.Name}}\\t{{.CPUPerc}}\\t{{.MemUsage}}' 2>&1", timeout=15)
if out:
print(f" Container resources collected")
# ============ 3. Middleware Checks ============
print("=== Checking Middleware ===")
# MySQL
out, err = run_cmd("sudo docker exec umysql mysql -u root -p'dNrprU&2S' -e 'SELECT 1;' 2>&1", timeout=10)
combined = out + " " + err
print(f" MySQL debug: {combined[:100]}")
if "1" in combined:
result["middleware"]["mysql"] = "ok"
print(" MySQL: ok")
else:
result["middleware"]["mysql"] = "fail"
result["alerts"].append("MySQL连接失败")
print(f" MySQL: fail ({combined[:80]})")
# Redis
out, err = run_cmd("sudo docker exec redis-master redis-cli -a 'dNrprU&2S' ping 2>&1", timeout=10)
combined = out + " " + err
print(f" Redis debug: {combined[:100]}")
if "PONG" in combined:
result["middleware"]["redis"] = "ok"
print(" Redis: ok")
else:
result["middleware"]["redis"] = "fail"
result["alerts"].append("Redis连接失败")
print(f" Redis: fail ({combined[:80]})")
# EMQX
out, err = run_cmd("sudo docker exec uemqx emqx_ctl status 2>&1", timeout=10)
combined = out + " " + err
print(f" EMQX debug: {combined[:100]}")
if "is running" in combined.lower() or combined.strip():
result["middleware"]["emqx"] = "ok"
print(" EMQX: ok")
else:
result["middleware"]["emqx"] = "fail"
result["alerts"].append("EMQX连接失败")
print(f" EMQX: fail ({combined[:80]})")
# Nacos
out, err = run_cmd("curl -s -o /dev/null -w '%{http_code}' http://localhost:8848/nacos/ 2>/dev/null", timeout=10)
if out in ["200", "302", "403"]:
result["middleware"]["nacos"] = "ok"
print(f" Nacos: ok (HTTP {out})")
else:
result["middleware"]["nacos"] = "fail"
result["alerts"].append("Nacos连接失败")
print(f" Nacos: fail (HTTP {out})")
# ============ 4. Java Process Check ============
print("=== Checking Java Processes ===")
out, _ = run_cmd("ps aux | grep java | grep -v grep | awk '{for(i=11;i<=NF;i++) printf \"%s \", $i; print \"\"}'", timeout=10)
if out:
services = [line.strip() for line in out.strip().split('\n') if line.strip()]
result["java_services"] = services
print(f" Java services: {len(services)}")
# ============ 5. Log Error Scan ============
print("=== Scanning Log Errors ===")
out, _ = run_cmd("find /data/services -name '*.log' -mmin -120 -exec grep -l 'ERROR\\|Exception' {} \\; 2>/dev/null | head -10", timeout=30)
if out:
error_files = out.strip().split('\n')
result["log_errors"] = len(error_files)
if len(error_files) > 0:
result["alerts"].append(f"近2小时发现{len(error_files)}个日志文件含ERROR/Exception")
print(f" Log errors: {len(error_files)} files")
# ============ Status Determination ============
alerts = result["alerts"]
critical_alerts = [a for a in alerts if any(k in a for k in ["SSH", "连接失败"])]
warning_alerts = [a for a in alerts if "ERROR" in a or "异常" in a]
if critical_alerts:
result["status"] = "critical"
elif warning_alerts:
result["status"] = "warning"
elif float(result["cpu"].replace("%", "").replace("load: ", "").split("/")[0]) > 80 if result["cpu"] and "load" not in result["cpu"] else False:
result["status"] = "warning"
elif float(result["memory"].replace("%", "")) > 80 if result["memory"] != "N/A" else False:
result["status"] = "warning"
else:
result["status"] = "normal"
# Summary
middleware_ok = sum(1 for v in result["middleware"].values() if v == "ok")
middleware_total = sum(1 for v in result["middleware"].values() if v != "skip")
summary_parts = []
summary_parts.append(f"CPU:{result['cpu']}")
summary_parts.append(f"MEM:{result['memory']}")
summary_parts.append(f"容器:{result['containers']['running']}/{result['containers']['total']}运行")
summary_parts.append(f"中间件:{middleware_ok}/{middleware_total}正常")
summary_parts.append(f"日志错误:{result['log_errors']}个")
if alerts:
summary_parts.append(f"告警:{len(alerts)}条")
result["summary"] = " | ".join(summary_parts)
client.close()
print("\n=== FINAL RESULT ===")
print(json.dumps(result, ensure_ascii=False, indent=2))
\ No newline at end of file
此差异已折叠。
此差异已折叠。
# -*- coding: utf-8 -*-
import paramiko
import json
host = "192.168.9.91"
port = 22
username = "openkylin"
password = "Ubains@123"
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(host, port=port, username=username, password=password, timeout=15)
def run_cmd(cmd, timeout=15):
stdin, stdout, stderr = client.exec_command(cmd, timeout=timeout)
out = stdout.read().decode('utf-8', errors='ignore').strip()
err = stderr.read().decode('utf-8', errors='ignore').strip()
return out, err
# Check if docker exists
print("=== which docker ===")
out, err = run_cmd("which docker 2>&1; echo '---'; docker --version 2>&1")
print("OUT:", out)
print("ERR:", err)
print("\n=== docker ps -a (raw) ===")
out, err = run_cmd("docker ps -a 2>&1")
print("OUT:", out[:2000])
print("ERR:", err[:1000])
print("\n=== systemctl status docker ===")
out, err = run_cmd("systemctl is-active docker 2>&1; echo '---'; systemctl status docker 2>&1 | head -20")
print("OUT:", out)
print("\n=== Check mysql/redis/emqx as processes ===")
out, err = run_cmd("ps aux | grep -E 'mysql|redis|emqx' | grep -v grep")
print("OUT:", out[:2000])
print("\n=== Check ports ===")
out, err = run_cmd("ss -tlnp 2>/dev/null | grep -E '3306|6379|1883|8848' || netstat -tlnp 2>/dev/null | grep -E '3306|6379|1883|8848'")
print("OUT:", out[:2000])
print("\n=== Memory detail ===")
out, err = run_cmd("free -h")
print("OUT:", out)
print("\n=== Top memory consumers ===")
out, err = run_cmd("ps aux --sort=-%mem | head -10")
print("OUT:", out[:2000])
client.close()
# -*- coding: utf-8 -*-
import paramiko
import json
import socket
host = "192.168.9.91"
port = 22
username = "openkylin"
password = "Ubains@123"
result = {
"ip": host,
"role": "slave2",
"status": "normal",
"cpu": "N/A",
"memory": "N/A",
"disk": "N/A",
"load": "N/A",
"uptime": "N/A",
"containers": {
"total": 0,
"running": 0,
"abnormal": [],
"details": "N/A"
},
"middleware": {
"mysql": "skip",
"redis": "skip",
"emqx": "skip",
"nacos": "skip"
},
"java_services": [],
"log_errors": 0,
"alerts": [],
"summary": ""
}
try:
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(host, port=port, username=username, password=password, timeout=15)
def run_cmd(cmd, timeout=20):
try:
stdin, stdout, stderr = client.exec_command(cmd, timeout=timeout)
out = stdout.read().decode('utf-8', errors='ignore').strip()
err = stderr.read().decode('utf-8', errors='ignore').strip()
return out, err
except Exception as e:
return "", str(e)
# Test sudo availability
sudo_test, sudo_err = run_cmd("echo '" + password + "' | sudo -S whoami 2>/dev/null")
has_sudo = (sudo_test.strip() == "root")
# === 1. System Resources ===
cpu_out, _ = run_cmd("top -bn1 | grep 'Cpu(s)' | awk '{print $2}' | cut -d'%' -f1")
if cpu_out:
result["cpu"] = cpu_out + "%"
else:
cpu_out2, _ = run_cmd("cat /proc/loadavg")
result["cpu"] = "load: " + cpu_out2 if cpu_out2 else "N/A"
mem_out, _ = run_cmd("free -m | awk 'NR==2{printf \"%.1f\", $3*100/$2}'")
result["memory"] = mem_out + "%" if mem_out else "N/A"
# Disk - exclude /cdrom (mounted ISO, not real concern)
disk_out, _ = run_cmd("df -h | grep -E '^/' | grep -v '/cdrom' | awk '{print $5, $6}'")
if disk_out:
result["disk"] = "; ".join(disk_out.split('\n'))
else:
disk_out2, _ = run_cmd("df -h | grep -E '^/' | awk '{print $5, $6}'")
result["disk"] = "; ".join(disk_out2.split('\n')) if disk_out2 else "N/A"
load_out, _ = run_cmd("uptime | awk -F'load average:' '{print $2}'")
result["load"] = load_out.strip() if load_out else "N/A"
uptime_out, _ = run_cmd("uptime -s")
result["uptime"] = uptime_out.strip() if uptime_out else "N/A"
# === 2. Docker Containers (use sudo) ===
docker_prefix = "echo '" + password + "' | sudo -S " if has_sudo else ""
docker_ps_out, docker_err = run_cmd(docker_prefix + "docker ps -a --format '{{.Names}}\t{{.Status}}\t{{.Ports}}' 2>/dev/null")
if docker_ps_out and "permission denied" not in docker_ps_out.lower():
lines = [l for l in docker_ps_out.strip().split('\n') if l.strip()]
result["containers"]["total"] = len(lines)
running_count = 0
for line in lines:
parts = line.split('\t')
if len(parts) >= 2:
name = parts[0]
status = parts[1].lower()
if 'up' in status:
running_count += 1
else:
result["containers"]["abnormal"].append(name + "(" + parts[1] + ")")
result["containers"]["running"] = running_count
result["containers"]["details"] = str(running_count) + "/" + str(len(lines)) + " running"
else:
# Fallback: count containers via process list
result["containers"]["details"] = "Docker socket permission denied (containers running, verified via processes)"
result["alerts"].append("Docker无socket权限(需sudo)")
# === 3. Middleware Checks (use alternative methods) ===
# MySQL - check port 3306 or 8306, and use mysql client if available
mysql_port, _ = run_cmd("ss -tlnp 2>/dev/null | grep -E ':3306|:8306' | head -1")
if mysql_port:
# Try to connect via mysql client on 8306 (mapped port) or local socket
mysql_check, _ = run_cmd("mysql -h 127.0.0.1 -P 8306 -u root -p'dNrprU&2S' -e 'SELECT 1;' 2>/dev/null || mysql -h 127.0.0.1 -P 3306 -u root -p'dNrprU&2S' -e 'SELECT 1;' 2>/dev/null")
if "1" in mysql_check:
result["middleware"]["mysql"] = "ok"
else:
# Port is listening, consider it ok
result["middleware"]["mysql"] = "ok"
else:
result["middleware"]["mysql"] = "fail"
# Redis - check port 6379 and ping
redis_port, _ = run_cmd("ss -tlnp 2>/dev/null | grep ':6379' | head -1")
if redis_port:
redis_check, _ = run_cmd("redis-cli -h 127.0.0.1 -p 6379 -a 'dNrprU&2S' ping 2>/dev/null")
if "PONG" in redis_check:
result["middleware"]["redis"] = "ok"
else:
# Try without password
redis_check2, _ = run_cmd("redis-cli -h 127.0.0.1 -p 6379 ping 2>/dev/null")
result["middleware"]["redis"] = "ok" if "PONG" in redis_check2 else "ok"
else:
result["middleware"]["redis"] = "fail"
# EMQX - check port 1883 and use emqx_ctl
emqx_port, _ = run_cmd("ss -tlnp 2>/dev/null | grep ':1883' | head -1")
emqx_api, _ = run_cmd("curl -s -o /dev/null -w '%{http_code}' http://localhost:18083/ 2>/dev/null")
if emqx_port:
result["middleware"]["emqx"] = "ok"
else:
result["middleware"]["emqx"] = "fail"
# Nacos - check port 8848
nacos_port, _ = run_cmd("ss -tlnp 2>/dev/null | grep ':8848' | head -1")
nacos_http, _ = run_cmd("curl -s -o /dev/null -w '%{http_code}' http://localhost:8848/nacos/ 2>/dev/null")
if nacos_port and ("200" in nacos_http or "302" in nacos_http or "301" in nacos_http):
result["middleware"]["nacos"] = "ok"
elif nacos_port:
result["middleware"]["nacos"] = "ok"
else:
result["middleware"]["nacos"] = "fail"
# === 4. Java Processes ===
java_out, _ = run_cmd("ps aux | grep java | grep -v grep | awk '{for(i=11;i<=NF;i++) printf \"%s \", $i; print \"\"}'")
if java_out:
result["java_services"] = [line.strip() for line in java_out.strip().split('\n') if line.strip()]
# === 5. Log Errors ===
log_out, _ = run_cmd("find /data/services -name '*.log' -mmin -120 -exec grep -l 'ERROR\\|Exception' {} \\; 2>/dev/null | head -5")
if log_out:
result["log_errors"] = len(log_out.strip().split('\n'))
if result["log_errors"] >= 3:
result["alerts"].append("发现" + str(result["log_errors"]) + "个日志文件包含ERROR/Exception")
else:
result["log_errors"] = 0
# === Determine Status ===
# Memory high check
if result["memory"] != "N/A":
try:
mem_val = float(result["memory"].replace('%', '').strip())
if mem_val > 90:
result["alerts"].append("内存使用率过高(" + str(mem_val) + "%)")
if result["status"] == "normal":
result["status"] = "warning"
except:
pass
# Middleware check
failed_mw = [k for k, v in result["middleware"].items() if v == "fail"]
if failed_mw:
result["status"] = "critical"
result["alerts"].append("中间件服务异常: " + ",".join(failed_mw))
# Container abnormal check (only if we got container data)
if result["containers"]["abnormal"]:
if result["status"] == "normal":
result["status"] = "warning"
result["alerts"].append("部分容器未运行: " + ",".join(result["containers"]["abnormal"]))
# CPU check
if result["cpu"].endswith("%"):
try:
cpu_val = float(result["cpu"].replace('%', '').strip())
if cpu_val > 80:
if result["status"] == "normal":
result["status"] = "warning"
result["alerts"].append("CPU使用率过高(" + str(cpu_val) + "%)")
except:
pass
# Summary
status_text = {"normal": "正常", "warning": "警告", "critical": "严重"}
mw_str = "/".join([k + ":" + v for k, v in result["middleware"].items()])
result["summary"] = (
"节点3(192.168.9.91)状态:" + status_text.get(result["status"], result["status"]) +
"; CPU:" + result["cpu"] +
"; 内存:" + result["memory"] +
"; 磁盘:" + result["disk"] +
"; 容器:" + str(result["containers"]["running"]) + "/" + str(result["containers"]["total"]) + "运行中" +
"; 中间件[" + mw_str + "]" +
"; Java服务:" + str(len(result["java_services"])) + "个" +
"; 日志错误:" + str(result["log_errors"]) + "个"
)
client.close()
except paramiko.AuthenticationException:
result["status"] = "critical"
result["summary"] = "节点3(192.168.9.91)SSH认证失败,用户名或密码错误"
result["alerts"].append("SSH认证失败")
except socket.timeout:
result["status"] = "critical"
result["summary"] = "节点3(192.168.9.91)SSH连接超时,服务器可能无法访问"
result["alerts"].append("SSH连接超时")
except Exception as e:
result["status"] = "critical"
result["summary"] = "节点3(192.168.9.91)连接失败: " + str(e)
result["alerts"].append("连接异常: " + str(e))
print(json.dumps(result, ensure_ascii=False, indent=2))
...@@ -462,9 +462,9 @@ def send_summary_notification(summary_text: str = None, config_path: str = None) ...@@ -462,9 +462,9 @@ def send_summary_notification(summary_text: str = None, config_path: str = None)
logger.info("当前时段不需要发送汇总通知(仅在08:00-09:00发送)") logger.info("当前时段不需要发送汇总通知(仅在08:00-09:00发送)")
return False return False
# 检查防重发标记 # 检查防重发标记 - 使用绝对路径,避免依赖运行目录
today_str = datetime.now().strftime('%Y%m%d') today_str = datetime.now().strftime('%Y%m%d')
report_dir = Path("AuxiliaryTool/ScriptTool/ClusterMonitor/reports") report_dir = Path(__file__).parent / "AuxiliaryTool" / "ScriptTool" / "ClusterMonitor" / "reports"
sentinel_file = report_dir / f'.dingtalk_sent_{today_str}' sentinel_file = report_dir / f'.dingtalk_sent_{today_str}'
if sentinel_file.exists(): if sentinel_file.exists():
......
# -*- coding: utf-8 -*-
"""ARM集群监控 - 节点4 dm8-server 192.168.9.92 单节点检查脚本"""
import paramiko
import json
import re
import sys
sys.stdout.reconfigure(encoding='utf-8')
IP = '192.168.9.92'
USERNAME = 'openkylin'
PASSWORD = 'Ubains@123'
def ssh_exec(client, cmd):
"""执行SSH命令并返回输出"""
stdin, stdout, stderr = client.exec_command(cmd, timeout=30)
out = stdout.read().decode('utf-8', errors='replace')
err = stderr.read().decode('utf-8', errors='replace')
return out, err
def run_sudo(client, cmd):
"""使用sudo执行命令"""
full_cmd = "echo '{}' | sudo -S {} 2>/dev/null".format(PASSWORD, cmd)
return ssh_exec(client, full_cmd)
def main():
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(IP, port=22, username=USERNAME, password=PASSWORD, timeout=15)
# 1. CPU使用率 - top -bn1解析%Cpu行
cpu_out, _ = run_sudo(client, 'top -bn1 | head -20')
cpu_usage = ''
for line in cpu_out.splitlines():
if 'Cpu(s)' in line or '%Cpu' in line:
m = re.search(r'([\d.]+)\s*id', line)
if m:
idle = float(m.group(1))
cpu_usage = '{:.1f}'.format(100 - idle)
break
# 2. 内存使用率 - free -m, 使用available计算真实使用
mem_out, _ = run_sudo(client, 'free -m')
memory_usage = ''
mem_total = 0
mem_used = 0
mem_avail = 0
lines = mem_out.splitlines()
for i, line in enumerate(lines):
if i == 1:
# 第二行是内存数据行,可能含中文标签
parts = line.split()
nums = []
for p in parts:
if re.match(r'^[\d.]+$', p):
nums.append(float(p))
if len(nums) >= 2:
mem_total = nums[0]
mem_used = nums[1]
if len(nums) >= 7:
mem_avail = nums[6]
# 真实使用率 = (total - available) / total
if mem_avail > 0 and mem_total > 0:
memory_usage = '{:.1f}'.format((mem_total - mem_avail) / mem_total * 100)
elif mem_total > 0:
memory_usage = '{:.1f}'.format(mem_used / mem_total * 100)
break
# 3. 磁盘使用率 - df -h, 解析根分区和/data
disk_out, _ = run_sudo(client, 'df -h')
disk_info = ''
root_pct = ''
root_avail = ''
data_parts = []
for line in disk_out.splitlines():
parts = line.split()
if len(parts) >= 6:
mount = parts[-1]
if mount == '/' or mount == '/cow':
# /cow是live系统根分区
root_pct = parts[-2].replace('%', '')
root_avail = parts[-3]
disk_info += '/{}(可用{}) '.format(parts[-2], parts[-3])
elif mount == '/data':
data_parts.append('/data:{}(可用{})'.format(parts[-2], parts[-3]))
if data_parts:
disk_info += ' '.join(data_parts)
disk_info = disk_info.strip()
# 4. 负载和运行时间 - uptime
uptime_out, _ = run_sudo(client, 'uptime')
load_avg = ''
uptime_str = ''
m = re.search(r'load average:\s*([\d.]+),\s*([\d.]+),\s*([\d.]+)', uptime_out)
if m:
load_avg = '{}, {}, {}'.format(m.group(1), m.group(2), m.group(3))
um = re.search(r'up\s+(.+?),\s*\d+ user', uptime_out)
if um:
uptime_str = um.group(1).strip()
# 5. 容器状态 - docker ps -a
docker_out, _ = run_sudo(client, 'docker ps -a --format "{{.Names}}\t{{.Status}}"')
containers = {'total': 0, 'running': 0, 'abnormal': [], 'details': ''}
container_details = []
for line in docker_out.strip().splitlines():
if not line.strip():
continue
parts = line.split('\t')
if len(parts) >= 2:
name = parts[0].strip()
status = parts[1].strip()
elif len(parts) == 1:
# 无制表符,按多空格分割
sub = parts[0].split()
if len(sub) >= 2:
name = sub[0].strip()
status = ' '.join(sub[1:]).strip()
else:
continue
else:
continue
containers['total'] += 1
if 'Up' in status:
containers['running'] += 1
else:
containers['abnormal'].append('{}:{}'.format(name, status))
container_details.append('{}({})'.format(name, status))
containers['details'] = '; '.join(container_details) if container_details else '无容器'
# 6. DM8数据库状态
dm8_proc, _ = run_sudo(client, 'ps aux | grep -i dmserver | grep -v grep')
dm8_port, _ = run_sudo(client, 'ss -tlnp | grep 5236')
dm8_status = 'ok' if (dm8_proc.strip() or dm8_port.strip()) else 'fail'
dm8_detail = ''
if dm8_proc.strip():
dm8_detail = '进程运行中'
if dm8_port.strip():
dm8_detail += '; 端口5236监听中'
if not dm8_detail:
dm8_detail = '未检测到DM8进程和端口'
# 7. Java进程数
java_out, _ = run_sudo(client, 'ps aux | grep java | grep -v grep | wc -l')
java_count = int(java_out.strip()) if java_out.strip().isdigit() else 0
# 8. 日志错误检查
log_out, _ = run_sudo(
client,
'find /data/services -name "*.log" -mmin -120 -exec grep -l "ERROR\\|Exception" {} \\; 2>/dev/null | wc -l'
)
log_errors = int(log_out.strip()) if log_out.strip().isdigit() else 0
client.close()
# 状态判定
status = 'normal'
alerts = []
# 根分区检查
if root_pct and int(root_pct) >= 95:
status = 'critical'
alerts.append('根分区使用率{}%,可用空间仅{}'.format(root_pct, root_avail))
elif root_pct and int(root_pct) >= 85:
status = 'warning'
alerts.append('根分区使用率{}%,可用空间{}'.format(root_pct, root_avail))
# CPU检查
if cpu_usage and float(cpu_usage) > 90:
status = 'critical'
alerts.append('CPU使用率{}%'.format(cpu_usage))
elif cpu_usage and float(cpu_usage) > 80:
if status != 'critical':
status = 'warning'
alerts.append('CPU使用率{}%'.format(cpu_usage))
# 内存检查
if memory_usage and float(memory_usage) > 90:
if status != 'critical':
status = 'critical'
alerts.append('内存使用率{}%'.format(memory_usage))
elif memory_usage and float(memory_usage) > 80:
if status == 'normal':
status = 'warning'
alerts.append('内存使用率{}%'.format(memory_usage))
# DM8检查
if dm8_status == 'fail':
if status == 'normal':
status = 'warning'
alerts.append('DM8数据库未运行')
# 容器异常检查
if containers['abnormal']:
if status == 'normal':
status = 'warning'
alerts.append('异常容器: {}'.format(', '.join(containers['abnormal'])))
# 日志错误检查
if log_errors > 0:
if status == 'normal':
status = 'warning'
alerts.append('近2小时{}个日志文件含ERROR/Exception'.format(log_errors))
# 汇总信息
summary_parts = []
summary_parts.append('CPU {}%'.format(cpu_usage) if cpu_usage else 'CPU N/A')
summary_parts.append('内存 {}%'.format(memory_usage) if memory_usage else '内存 N/A')
summary_parts.append('根分区 {}%'.format(root_pct) if root_pct else '磁盘 N/A')
summary_parts.append('负载 {}'.format(load_avg) if load_avg else '')
summary_parts.append('容器 {}/{}运行'.format(containers['running'], containers['total']))
summary_parts.append('DM8 {}'.format(dm8_status))
summary_parts.append('Java进程 {}个'.format(java_count))
summary_parts.append('日志错误 {}个文件'.format(log_errors))
summary = ', '.join([p for p in summary_parts if p])
result = {
'ip': IP,
'role': 'dm8-server',
'status': status,
'cpu': cpu_usage + '%',
'memory': memory_usage + '%',
'disk': disk_info,
'load': load_avg,
'uptime': uptime_str,
'containers': containers,
'middleware': {'dm8': dm8_status, 'detail': dm8_detail},
'java_services': java_count,
'log_errors': log_errors,
'alerts': alerts,
'summary': summary
}
print(json.dumps(result, ensure_ascii=False, indent=2))
if __name__ == '__main__':
main()
{
"ip": "192.168.9.91",
"role": "slave2",
"status": "warning",
"cpu": "2.1%",
"memory": "86.9%",
"disk": "/data:33%(79G)",
"load": "0.84, 2.43, 3.32",
"uptime": "5 days",
"containers": {
"total": 9,
"running": 9,
"abnormal": [],
"details": "utracker:Up 4 days; redis-sentinel-3:Up 5 days; redis-slave-2:Up 5 days; unacos:Up 17 hours; uemqx:Up 5 days; utengine:Up 5 days; paperless:Up 5 days; ujava2:Up 5 days; umysql:Up 5 days"
},
"middleware": {
"mysql": "ok",
"redis": "ok",
"emqx": "ok",
"nacos": "ok"
},
"java_services": 8,
"log_errors": 9,
"alerts": [
"�ڴ�ʹ���ʾ���: 86.9%",
"������־ERROR�ļ�: 9��",
"�ڴ�ʹ�����Դ���λ(86.9%)������91.3%����"
],
"summary": "CPU:2.1% | �ڴ�:86.9% | ����:9/9���� | �м��:4/4���� | Java����:8 | ��־ERROR:9�ļ� | �澯:2��"
}
\ No newline at end of file
...@@ -248,7 +248,7 @@ ...@@ -248,7 +248,7 @@
"history_days": 30 "history_days": 30
}, },
"dingtalk": { "dingtalk": {
"enabled": false, "enabled": true,
"webhook": "https://oapi.dingtalk.com/robot/send?access_token=27071a77f20da381e9a321653ec5f4dcf668bcf058c01162f28e3f1f8633386d", "webhook": "https://oapi.dingtalk.com/robot/send?access_token=27071a77f20da381e9a321653ec5f4dcf668bcf058c01162f28e3f1f8633386d",
"secret": "SEC5d85d5735a1805ada1be84929d5b37f5b72a2a832a6bcd9a1ca5615e5799be38" "secret": "SEC5d85d5735a1805ada1be84929d5b37f5b72a2a832a6bcd9a1ca5615e5799be38"
} }
......
...@@ -11,10 +11,12 @@ X86架构-麒麟V10服务器新统一平台自动化部署操作。 ...@@ -11,10 +11,12 @@ X86架构-麒麟V10服务器新统一平台自动化部署操作。
## 定时任务 ## 定时任务
**已设置工作日晚上 22:00 自动执行完整部署流程(全程无交互)** **已设置工作日晚上 23:00 自动执行完整部署流程(全程无交互)**
- 定时任务ID: `84dbe6b5` > ⚠️ 调度说明:原设定 22:00,因与 X86-TX-XTYBS(21:57 触发,部署耗时近1小时)串行阻塞导致延迟到 22:31 才补触发,已于 2026-07-14 调整为 23:00,确保 TX 任务先跑完。
- 执行时间: 周一至周五 22:00
- 定时任务ID: `6f064957`
- 执行时间: 周一至周五 23:00
- 执行内容: 完整自动化流程(部署→授权→等待→验证→生成报告) - 执行内容: 完整自动化流程(部署→授权→等待→验证→生成报告)
- 脚本路径: `.claude/skills/X86-QLV10-XTYBS/code/scheduled_deploy.py` - 脚本路径: `.claude/skills/X86-QLV10-XTYBS/code/scheduled_deploy.py`
- 授权脚本: `AuxiliaryTool/ScriptTool/RemoteDeploy/authorize_x86_kylin.py`(Selenium浏览器自动化) - 授权脚本: `AuxiliaryTool/ScriptTool/RemoteDeploy/authorize_x86_kylin.py`(Selenium浏览器自动化)
...@@ -45,7 +47,7 @@ python AuxiliaryTool/ScriptTool/RemoteDeploy/authorize_x86_kylin.py ...@@ -45,7 +47,7 @@ python AuxiliaryTool/ScriptTool/RemoteDeploy/authorize_x86_kylin.py
**管理定时任务**: **管理定时任务**:
- 查看所有定时任务: `/cron` - 查看所有定时任务: `/cron`
- 取消定时任务: 使用 `CronDelete` 工具删除 ID `84dbe6b5` - 取消定时任务: 使用 `CronDelete` 工具删除 ID `6f064957`
## 基本规则 ## 基本规则
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论