diff --git a/scripts/daily-report.sh b/scripts/daily-report.sh new file mode 100644 index 0000000..2fcf78d --- /dev/null +++ b/scripts/daily-report.sh @@ -0,0 +1,116 @@ +#!/bin/bash +# 每日健康报告 — 发送格式化摘要邮件到管理员 +# 部署:cp 到服务器 /root/rust/scripts/daily-report.sh,cron 每日执行 + +set -e + +TO="m943790568@163.com" +DATE=$(date "+%Y-%m-%d") +HOST=$(hostname) + +# ---------- 采集数据 ---------- + +UPTIME=$(uptime -p | sed 's/up //') +LOAD=$(uptime | awk -F'load average:' '{print $2}' | xargs) +DISK_USED=$(df -h / | awk 'NR==2{print $3}') +DISK_TOTAL=$(df -h / | awk 'NR==2{print $2}') +DISK_PCT=$(df -h / | awk 'NR==2{print $5}') +MEM_USED=$(free -h | awk '/Mem/{print $3}') +MEM_TOTAL=$(free -h | awk '/Mem/{print $2}') +MEM_PCT=$(free | awk '/Mem/{printf "%.0f", $3/$2 * 100}') +CPU_TEMP=$(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null | awk '{printf "%.1f°C", $1/1000}' || echo "N/A") + +# Docker +DOCKER_STATUS=$(docker ps --format '{{.Names}} {{.Status}}' 2>/dev/null || echo "Docker 不可用") + +# SSL 证书 +SSL_EXPIRY=$(echo "" | openssl s_client -connect xmclassmate.top:443 -servername xmclassmate.top 2>&1 | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2 || echo "检测失败") +SSL_DAYS=$(( ($(date -d "$SSL_EXPIRY" +%s 2>/dev/null) - $(date +%s)) / 86400 )) || SSL_DAYS="?" + +# 服务状态 +GREEN_STATUS=$(systemctl is-active rust-backend-green.service 2>/dev/null || echo "unknown") +BLUE_STATUS=$(systemctl is-active rust-backend-blue.service 2>/dev/null || echo "unknown") +NGINX_STATUS=$(systemctl is-active nginx 2>/dev/null || echo "unknown") + +# 最近备份 +LAST_BACKUP=$(ls -1t /root/rust/backups/milkydata/ 2>/dev/null | head -1) +BACKUP_AGE="未知" +if [ -n "$LAST_BACKUP" ]; then + BACKUP_TIME=$(stat -c %Y "/root/rust/backups/milkydata/$LAST_BACKUP" 2>/dev/null) + NOW=$(date +%s) + AGE_HOURS=$(( (NOW - BACKUP_TIME) / 3600 )) + if [ "$AGE_HOURS" -lt 24 ]; then + BACKUP_AGE="✅ ${AGE_HOURS}小时前" + elif [ "$AGE_HOURS" -lt 48 ]; then + BACKUP_AGE="⚠️ ${AGE_HOURS}小时前" + else + BACKUP_AGE="❌ ${AGE_HOURS}小时前" + fi +fi + +# Fail2Ban 封禁统计 +SSH_BANS=$(sudo fail2ban-client status sshd 2>/dev/null | grep "Currently banned" | awk '{print $NF}' || echo "0") +NGINX_BANS=$(sudo fail2ban-client status nginx-botsearch 2>/dev/null | grep "Currently banned" | awk '{print $NF}' || echo "0") + +# 近期错误数(昨天 journalctl) +YESTERDAY_ERRORS=$(journalctl -u rust-backend-green.service --since "1 day ago" --priority err --no-pager 2>/dev/null | wc -l) +YESTERDAY_WARNS=$(journalctl -u rust-backend-green.service --since "1 day ago" --priority warning --no-pager 2>/dev/null | wc -l) + +# 应用统计(昨天活跃用户) +ACTIVE_USERS=$(journalctl -u rust-backend-green.service --since "1 day ago" --no-pager 2>/dev/null | grep -c "user_id=\|登录成功\|上传成功" || echo "0") +API_COUNT=$(journalctl -u rust-backend-green.service --since "1 day ago" --no-pager 2>/dev/null | grep -c "INFO\|WARN\|ERROR" || echo "0") + +# ---------- 构建邮件正文 ---------- + +SUBJECT="[ASD 服务器报告] ${DATE} — ${HOST}" + +MAIL=$(cat <