- infra/cicd:docker-compose(gitea/jenkins)、JCasC(凭据统一 ${ENV} 注入,无硬编码)、
备份/恢复、健康检查、凭据轮换与 git 历史清除脚本
- docs/deployment/cicd:安装、高可用备份监控、凭据事故复盘
- .env.example 仅为占位模板;真实 .env 由 .gitignore 排除
80 lines
3.0 KiB
Bash
Executable File
80 lines
3.0 KiB
Bash
Executable File
#!/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
|