--- name: "pbs-backup-stall-diag" description: "诊断 proxmox-backup-client 备份疑似停滞。增量备份跨慢盘(WSL /mnt)或大目录时进度滞后时用。判断真卡死与慢速推进。" status: proposal version: "v1" date: "2026-09-02T13:05:33.862Z" --- # PBS 备份停滞诊断 当 proxmox-backup-client 备份在日志里长时间停在同一个 `processed X GiB ... uploaded 0 B`,判断是**真卡死**还是**慢速推进**(常见于跨盘/大目录增量备份)。 ## 背景 增量备份只传变化数据,但**校验变化前要逐文件读取对比**。当源在慢速介质(WSL 的 `/mnt/d`、`/mnt/e` Windows NTFS 挂载,走 9P 协议),或含海量小文件时,I/O 成为瓶颈:表现为 CPU 占比低(约 1-2%)、processed 长时不变、uploaded 0 B。这是**预期的慢,不是故障**。 单看 `/var/log/-autosync.log` 无法区分——它只在整文件边界更新。 ## 诊断过程 1. 定位进程:`pgrep -f "proxmox-backup-client backup"` 取 PID。 2. 看进程状态与 CPU(S 状态 + 低 CPU = 等在 I/O,非僵死): `ps -o pid,stat,pcpu,etime -p ` 3. **确认在推进(关键)**:查它正打开的文件—— `ls -l /proc//fd | grep -E "/mnt|pxar"` 若 fd 指向源目录深层具体文件(如 `.../Media/_m...`)且打开时间在变化,说明正在逐个读文件做校验。 4. 看是否已连到目标:`ss -tnp | grep :8007`,有 ESTAB 即在与 PBS 通信。 5. 结合源规模估算:`du -sh <源>` + `find <源> -type f | wc -l`。文件数以千计、源在 /mnt 跨盘时,耐心等,勿贸然 kill。 ## 判定 - 进程 S/Ssl 状态、CPU 低、fd 在变化指向源文件、连 :8007 → **慢速推进,等待**。 - 进程消失、或 fd 长期不动且无网络、或 CPU 也 0 且无 I/O → 才考虑真卡死,需 kill 重跑。 ## 坑 - 服务端快照目录里只看到空的 `*.tmp_didx`、0 字节,不代表卡死——内容要等本地上传阶段才开始写入。 - 日志时间戳滞后是 systemd `StandardOutput=append` 的 flush 延迟,别据此误判。 ## 网络通道补救(关键恢复) 慢速推进诊断通过后,若**长时间(如 15-20 分钟)仍无实质上传、最终报 `Error: timed out` + `HTTP/2.0 connection failed` + `catalog upload error - channel closed`**,且客户端与 PBS 本就在同一局域网——这通常是 **tailscale/中继传输通道在大数据量时卡死**,不是介质慢。恢复方法: 1. 查 PBS 服务器的局域网 IP:`ssh root@pbs01 'ip -4 addr show | grep "inet "'`(另一网卡常有如 `192.168.3.11`,tailscale 是 `100.115.x.x`)。 2. 在客户端 ping 该 LAN IP;1ms 级延迟即同网可达。 3. 把备份 repository 从 tailscale 主机名(`@pbs01`)改为 **LAN IP 直连**:`export PBS_REPOSITORY='backup@pbs!@:'`。 4. 命中即整库备份从 20 分钟超时失败变为约 90 秒成功(增量复用 ~95%)。 服务端佐证:tailscale 失败时服务端 task 日志停在 `POST /dynamic_chunk` 后长时间无后续;LAN 直连时 `successfully added chunk ...` 连续刷新。 注意:LAN 直连前提是客户端与 PBS 同网;跨地/异地时此地址不可达,需回退 tailscale——可让脚本动态判断(LAN ping 通则用 LAN,否则 tailscale)。 坑:**验证 LAN 是否解决时,别给 client 进程包一层人工 `timeout <秒>` 外壳**——proxmox-backup-client 收尾需把 catalog/finish 状态完整写回,若 timeout 在外壳里掐断了收尾,服务端会报 `backup ended but finished state is not set` 并删除已传完的快照(整库数据其实已传完)。恢复:去掉外层 timeout、让 client 自然结束即可完整成功。跑系统 service 则靠 service 的 `TimeoutStartSec` 兜底,不要额外加 client 级 timeout。