服务器上跑 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
This commit is contained in:
@@ -120,20 +120,36 @@ case "$OUT_DIR/" in
|
|||||||
esac
|
esac
|
||||||
ok "备份目录 $OUT_DIR"
|
ok "备份目录 $OUT_DIR"
|
||||||
|
|
||||||
|
# 拿回来的数要进 [ ] 比大小,不是数字就当「读不出来」,不能让它把整个备份带崩
|
||||||
|
digits_or_zero() {
|
||||||
|
case "$1" in
|
||||||
|
'' | *[!0-9]*) printf '0\n' ;;
|
||||||
|
*) printf '%s\n' "$1" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
# datallowconn 是为了跳过 template0:它不让连,pg_database_size 也算不了
|
# datallowconn 是为了跳过 template0:它不让连,pg_database_size 也算不了
|
||||||
db_bytes=$(docker exec "$CONTAINER" psql -U "$DB_USER" -d postgres -tAc \
|
db_bytes=$(docker exec "$CONTAINER" psql -U "$DB_USER" -d postgres -tAc \
|
||||||
"select coalesce(sum(pg_database_size(datname)), 0)::bigint from pg_database where datallowconn" \
|
"select coalesce(sum(pg_database_size(datname)), 0)::bigint from pg_database where datallowconn" \
|
||||||
2>/dev/null | tr -d '[:space:]' || true)
|
2>/dev/null | tr -d '[:space:]' || true)
|
||||||
[ -n "${db_bytes:-}" ] || db_bytes=0
|
db_bytes=$(digits_or_zero "${db_bytes:-}")
|
||||||
|
|
||||||
free_bytes=$(df -Pk "$OUT_DIR" | awk 'NR == 2 { print $4 * 1024 }')
|
# df 的第 4 列是 KB。**原样取字段,不让 awk 参与算术** —— Debian 的 /usr/bin/awk 是
|
||||||
ok "库 $(human "$db_bytes"),磁盘剩 $(human "$free_bytes")"
|
# mawk,超过 2^31 的数会按 OFMT(%.6g)打成 `4.29685e+10`,丢回 [ ] 就是
|
||||||
|
# 「需要整数表达式」,脚本当场退出。换算放到 bash 的 64 位算术里做,谁的 awk 都一样。
|
||||||
if [ "$db_bytes" -gt 0 ] && [ "$free_bytes" -lt "$db_bytes" ]; then
|
free_kb=$(digits_or_zero "$(df -Pk "$OUT_DIR" | awk 'NR == 2 { print $4 }')")
|
||||||
[ "$FORCE" -eq 1 ] \
|
free_bytes=$(( free_kb * 1024 ))
|
||||||
|| die "磁盘余量比库还小。压缩后通常小一个数量级,确认够用就加 --force
|
# 余量检查是**提醒**,不是前置条件:读不出来就跳过,不能因为读不到 df 就不备份
|
||||||
|
if [ "$free_bytes" -eq 0 ]; then
|
||||||
|
warn "库 $(human "$db_bytes"),磁盘余量读不出来 —— 跳过余量检查"
|
||||||
|
else
|
||||||
|
ok "库 $(human "$db_bytes"),磁盘剩 $(human "$free_bytes")"
|
||||||
|
if [ "$db_bytes" -gt 0 ] && [ "$free_bytes" -lt "$db_bytes" ]; then
|
||||||
|
[ "$FORCE" -eq 1 ] \
|
||||||
|
|| die "磁盘余量比库还小。压缩后通常小一个数量级,确认够用就加 --force
|
||||||
—— 备份把生产磁盘写满,比没有备份更糟"
|
—— 备份把生产磁盘写满,比没有备份更糟"
|
||||||
warn "磁盘余量不足,--force 已指定,继续"
|
warn "磁盘余量不足,--force 已指定,继续"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ---------------------------------------------------------------- 导出
|
# ---------------------------------------------------------------- 导出
|
||||||
|
|||||||
Reference in New Issue
Block a user