- 调整单金额恒正:schema 正则拦格式(非负两位小数、≤12 位整数防 NUMERIC(14,2) 溢出)+ 服务层 Decimal>0 语义校验——负数会反转补发/ 扣减语义,'abc' 原样入库会以 500 暴露 - 分界天数参数解析:int(parse_fraction(...)) 替代 int(参数原文)—— '360.0' 是 INT 参数的合法入库值(Fraction 分母为 1),直接 int(str) 抛 ValueError 会让整月核算 500 - logo 旧文件清理容错:OSError 只记 warning——裸抛会把成功的 logo 更新 记成失败审计并 500(库中 logo_path 却已是新值,审计与事实相反) - health_check.sh:Redis 探活改容器内环境变量展开(密码不进宿主进程 命令行,模式同 backup_full.sh);compose redis 补 REDIS_PASSWORD - restore_drill.sh:行数核对扩到全部 32 张业务表(原 16 张漏 V7 四表、 二次分配等核心表,备份漏表演练全绿);查询失败回显 '?' 一律判 ✗ (原 '?'=='?' 判一致,表缺失时误报「备份可恢复」) - 并入 88 会话的 #12 实现:manager.personal.included 开关消费 (_build_manager_aggregates 参数化,测试见 828b573) - 测试:调整单金额恒正 5 稿、INT 参数小数原文核算 200 回归;单测 469 Co-Authored-By: Claude Code <noreply@anthropic.com>
107 lines
3.6 KiB
Bash
107 lines
3.6 KiB
Bash
#!/usr/bin/env bash
|
||
# 运维健康检查 —— 容器/磁盘/备份新鲜度/登录异常(⑨ 输出一份可读报告)
|
||
#
|
||
# 用法:在项目根目录执行 bash scripts/health_check.sh
|
||
# 每项 PASS/WARN/FAIL,最后给出结论。WARN/FAIL 时退出码非零提示运维介入。
|
||
|
||
set -uo pipefail
|
||
|
||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||
cd "$ROOT"
|
||
|
||
if [[ -f docker/.env ]]; then
|
||
# shellcheck disable=SC1091
|
||
source docker/.env
|
||
fi
|
||
|
||
ISSUES=0
|
||
report() { printf "%-10s %s\n" "$1" "$2"; }
|
||
warn() { report "WARN" "$1"; ISSUES=$((ISSUES+1)); }
|
||
fail() { report "FAIL" "$1"; ISSUES=$((ISSUES+1)); }
|
||
pass() { report "PASS" "$1"; }
|
||
|
||
echo "======== 衍水工资系统 健康检查 $(date '+%Y-%m-%d %H:%M:%S') ========"
|
||
|
||
# 1. 容器健康
|
||
for C in ys-mysql-dev ys-redis-dev; do
|
||
if ! docker inspect "$C" >/dev/null 2>&1; then
|
||
fail "容器 $C 不存在"
|
||
continue
|
||
fi
|
||
STATUS="$(docker inspect -f '{{.State.Health.Status}}' "$C" 2>/dev/null || echo none)"
|
||
RUNNING="$(docker inspect -f '{{.State.Running}}' "$C" 2>/dev/null)"
|
||
if [[ "$RUNNING" == "true" && "$STATUS" == "healthy" ]]; then
|
||
pass "容器 $C 运行中且健康"
|
||
elif [[ "$RUNNING" == "true" ]]; then
|
||
warn "容器 $C 运行中但健康检查=$STATUS"
|
||
else
|
||
fail "容器 $C 未运行"
|
||
fi
|
||
done
|
||
|
||
# 2. 磁盘水位
|
||
DISK_PCT="$(df -h "$ROOT" | awk 'NR==2 {gsub(/%/,"",$5); print $5}')"
|
||
if [[ -z "$DISK_PCT" ]]; then
|
||
warn "磁盘信息读取失败"
|
||
elif (( DISK_PCT < 80 )); then
|
||
pass "磁盘使用率 ${DISK_PCT}%(阈值 80%)"
|
||
elif (( DISK_PCT < 90 )); then
|
||
warn "磁盘使用率 ${DISK_PCT}%(建议清理)"
|
||
else
|
||
fail "磁盘使用率 ${DISK_PCT}%(高危,立即清理)"
|
||
fi
|
||
|
||
# 3. 备份新鲜度
|
||
BACKUP_DIR="$ROOT/db/backups"
|
||
LATEST="$(ls -t "$BACKUP_DIR"/payroll_*.sql.gz 2>/dev/null | head -1)"
|
||
if [[ -z "$LATEST" ]]; then
|
||
warn "未找到任何备份(应每日备份)"
|
||
else
|
||
AGE_H=$(( ($(date +%s) - $(stat -c %Y "$LATEST")) / 3600 ))
|
||
if (( AGE_H < 24 )); then
|
||
pass "最新备份 $(basename "$LATEST"),${AGE_H} 小时前"
|
||
elif (( AGE_H < 48 )); then
|
||
warn "最新备份已 ${AGE_H} 小时前(超过 24 小时)"
|
||
else
|
||
fail "最新备份已 ${AGE_H} 小时前(备份任务可能已停)"
|
||
fi
|
||
fi
|
||
|
||
# 4. Redis 存活(密码经容器内环境变量展开,不出现在宿主进程命令行;
|
||
# 写法同 backup_full.sh 的 MYSQL_ROOT_PASSWORD)
|
||
if [[ -n "${REDIS_PASSWORD:-}" ]]; then
|
||
if docker exec ys-redis-dev sh -c 'redis-cli --no-auth-warning -a "$REDIS_PASSWORD" ping' 2>/dev/null | grep -q PONG; then
|
||
pass "Redis 响应 PONG"
|
||
else
|
||
warn "Redis ping 无响应(检查 REDIS_PASSWORD 或容器状态)"
|
||
fi
|
||
else
|
||
warn "docker/.env 缺 REDIS_PASSWORD,跳过 Redis 探活"
|
||
fi
|
||
|
||
# 5. 登录日志异常(24h 失败次数)
|
||
if [[ -n "${MYSQL_ROOT_PASSWORD:-}" ]] && docker inspect ys-mysql-dev >/dev/null 2>&1; then
|
||
FAILS=$(docker exec ys-mysql-dev sh -c \
|
||
"mysql -uroot -p\"\$MYSQL_ROOT_PASSWORD\" ${MYSQL_DATABASE:-payroll} -N -B -e \"
|
||
SELECT COUNT(*) FROM login_logs
|
||
WHERE success = 0 AND create_time > NOW() - INTERVAL 24 HOUR;\" 2>/dev/null" || echo "?")
|
||
if [[ "$FAILS" == "?" ]]; then
|
||
warn "登录日志查询失败"
|
||
elif (( FAILS < 10 )); then
|
||
pass "24h 登录失败 ${FAILS} 次(阈值 10)"
|
||
else
|
||
warn "24h 登录失败 ${FAILS} 次(可能有暴力破解,建议核查)"
|
||
fi
|
||
else
|
||
warn "跳过登录日志检查(无凭据或容器未运行)"
|
||
fi
|
||
|
||
echo "=============================================================="
|
||
if (( ISSUES == 0 )); then
|
||
echo "结论:全部通过,系统健康。"
|
||
exit 0
|
||
else
|
||
echo "结论:发现 $ISSUES 项需关注(见上)。"
|
||
exit 1
|
||
fi
|