Files
zhangxiang 4ab2f3cd8e chore(infra): 新增 Gitea+Jenkins CI/CD 部署与凭据整改
- infra/cicd:docker-compose(gitea/jenkins)、JCasC(凭据统一 ${ENV} 注入,无硬编码)、
  备份/恢复、健康检查、凭据轮换与 git 历史清除脚本
- docs/deployment/cicd:安装、高可用备份监控、凭据事故复盘
- .env.example 仅为占位模板;真实 .env 由 .gitignore 排除
2026-09-20 10:37:57 +08:00

80 lines
3.0 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# ============================================================
# 容器日志兜底截断
#
# 为什么需要它(2026-09-14 实测事故):
# novalon-cicd/docker-compose.yml 里明明配了
# logging: { driver: json-file, options: { max-size: 10m, max-file: 3 } }
# 但运行中容器的 HostConfig.LogConfig 实测为 {"Type":"json-file","Config":{}}
# —— 配置从未生效,Gitea 单份日志涨到 849MB,占掉整盘 4%。
#
# 根因:logging 驱动参数在**容器创建时**固化,事后改 compose 不重建则不生效。
#
# 本脚本是**临时兜底**,不是终态。
# 终态:用 infra/cicd/docker-compose.gitea.yml 重建容器(含正确 logging 配置),
# 之后本脚本可退化为纯监控用途。
#
# 用法:
# ./truncate-container-logs.sh # 截断超过阈值的日志
# ./truncate-container-logs.sh --check # 只报告,不截断
# ./truncate-container-logs.sh --threshold 50 # 自定义阈值(MB)
# ============================================================
set -uo pipefail
THRESHOLD_MB=100
CHECK_ONLY=0
# 用 while 而非 for 解析:for 迭代的是展开后的固定列表,
# 循环内 shift 不会改变已排定的迭代序列,导致 `--check --threshold 50` 取错值
while [[ $# -gt 0 ]]; do
case "$1" in
--check) CHECK_ONLY=1; shift ;;
--threshold) THRESHOLD_MB="${2:-100}"; shift 2 ;;
-h|--help) sed -n '2,22p' "$0"; exit 0 ;;
*) echo "未知参数: $1" >&2; exit 2 ;;
esac
done
LOG_ROOT="${LOG_ROOT:-/var/lib/docker/containers}"
ts() { date "+%Y-%m-%d %H:%M:%S"; }
echo "[$(ts)] 容器日志检查(阈值 ${THRESHOLD_MB}MB,模式 $([[ $CHECK_ONLY == 1 ]] && echo 只读 || echo 截断)"
TOTAL_BEFORE=0
TOTAL_AFTER=0
HIT=0
while IFS= read -r f; do
[[ -f "$f" ]] || continue
size_mb=$(( $(stat -c %s "$f") / 1048576 ))
[[ $size_mb -lt $THRESHOLD_MB ]] && continue
HIT=$((HIT + 1))
TOTAL_BEFORE=$((TOTAL_BEFORE + size_mb))
cid=$(basename "$(dirname "$f")")
cname=$(docker inspect -f '{{.Name}}' "$cid" 2>/dev/null | sed 's|^/||' || echo "$cid")
echo " ⚠️ ${cname}: ${size_mb}MB ($f)"
if (( CHECK_ONLY == 0 )); then
# truncate 对运行中的容器安全:Docker 以 O_APPEND 写,截断后继续追加
truncate -s 0 "$f" && echo " → 已截断"
TOTAL_AFTER=$((TOTAL_AFTER + $(stat -c %s "$f") / 1048576))
fi
done < <(find "$LOG_ROOT" -maxdepth 2 -name '*-json.log' 2>/dev/null)
if (( HIT == 0 )); then
echo " ✅ 无日志超过 ${THRESHOLD_MB}MB"
else
echo " 命中 $HIT 个"
if (( CHECK_ONLY == 0 )); then
echo " 释放约 $((TOTAL_BEFORE - TOTAL_AFTER))MB"
df -h / | awk 'NR==2{print " 磁盘: 已用 "$5", 可用 "$4}'
fi
fi
# 提醒:若命中说明 logging 配置仍未生效,需要重建容器才是终态修复
if (( HIT > 0 )); then
echo " ️ 命中的容器说明其 logging 轮转未生效 —— 请用带 logging 配置的 compose 重建容器(终态修复)"
fi