服务器上跑 backup-db.sh 报: docker/backup-db.sh: 第 132 行:[: 4.29685e+10: 需要整数表达式 `df -Pk | awk 'NR==2 { print $4 * 1024 }'` 让 awk 做了那个乘法。**mawk 1.3.3** (老 Debian 的 /usr/bin/awk)打印超过 2^31 的整数时会退回 OFMT(%.6g),42968547328 就成了 `4.29685e+10`,丢回 [ ] 比大小当场退出。用 debian:buster-slim 复现出了 一模一样的字符串;mawk 1.3.4(现在的 stable)和 busybox awk 都正常打整数, 我本机是 gawk,所以测不出来。 改成原样取 df 的第 4 列(KB),乘 1024 放到 bash 的 64 位算术里做,谁的 awk 都一样。 另外加一层 digits_or_zero:df 或 psql 返回的东西不是纯数字就当「读不出来」, **跳过余量检查照常备份** —— 余量检查是提醒,不该因为读不到它就不备份了。 (顺带把「磁盘剩 0.0 B」那句误导的输出并进警告里。) clear-sessions.sh 里那句 awk 求和也过了一遍:Redis 键数不可能到 2^31,不受影响。 验证:正常路径照旧;把 free_kb 强行喂成 `4.29685e+10`,现在是一条警告加一次 完整备份,不再退出。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KqjE6qPo67fqVDKn6Bx7yd
原来手敲的那条 docker compose exec -T oj-postgres pg_dumpall -c -U onlinejudge > db_backup_xxx.sql 在服务器上报 `service "oj-postgres" is not running`。容器明明在跑 —— 线上是外接 形态,postgres 由 /root/OJDeploy/docker-compose.yml 起,不归 OJ2 这套 compose 管; compose.debian.yml 里那个 oj-postgres 挂着 `profiles: ["local-data"]`,只在自带 数据形态下启动。所以脚本直接按容器名 `docker exec`,跟谁起的无关,两种形态都能用。 比原来那条命令多做的事: - **先写 .partial,验完才改名**。`> file.sql` 中途失败(容器挂了、盘满了、 pg_dumpall 报错)会留个半截文件,看着像备份,等到要恢复那天才发现不是。 中断也清掉。 - **验完整性**。gzip -t,再检查结尾有没有「PostgreSQL database cluster dump complete」,缺了就当失败。 - **umask 077 + chmod 600**。备份里有 user.raw_password(明文密码,本来就是留给 老师查的)和角色口令散列,不该落成 644。 - **自检真连一次库**(psql -c 'select 1' 而不是 pg_isready)。后者用户名写错照样 说 OK,要到 pg_dumpall 才炸出一句 role does not exist。 - **默认存到仓库外面**。deploy.sh 头部那条 rsync 带 --delete,备份放仓库里下次 部署就没了;真放进去了会警告。 - **保留策略带兜底**。删超期的,但最新 3 份永远保留 —— 时钟错乱或者 --keep-days 手滑填 0,都不该把手头唯一的备份删掉。 - **磁盘余量检查**。剩余空间比库还小就拒绝,--force 才继续。备份把生产盘写满比 没备份更糟。 默认 gzip,--plain 关掉。头部写了 cron 的写法,以及恢复时那几条 `does not exist` / `already exists` 是 pg_dumpall -c 的正常噪音。 本机 dev 库(245 MiB)实跑:正常路径 38.9 MiB gz / 2 秒;容器名写错、用户名写错都在 自检拦住;导出中途失败后 .partial 被清掉;保留策略造 5 份 30 天前的 → 删 5 留 3, 把全部文件做旧 → 仍然保住最新 3 份。**恢复也真跑了**:起一个干净的 postgres:16-alpine 灌进去,submission=12 / user=11 / problem=20 / 28 张表,和原库一致。 只管数据库。判题测试点在 data/backend/test_case,不在库里,那份还没有备份手段。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KqjE6qPo67fqVDKn6Bx7yd