rsync增量同步文件未更新因默认依赖大小和修改时间判断,nfs等场景mtime不准导致跳过;应加--times保留时间戳或--checksum校验内容;ssh连接失败需先排查sshd、防火墙、地址;--exclude路径匹配相对源路径且须在源前;cron中需显式指定私钥并设600权限。

rsync 增量同步时文件没更新?检查 --times 和 --checksum
rsync 默认靠文件大小 + 修改时间判断是否跳过,但 NFS、某些容器挂载或跨时区同步时,mtime 可能不准,导致该传的没传。
常见现象是目标端文件内容旧,但 rsync 却显示 “up to date”。
解决方法:
- 加
--times强制保留源时间戳(避免因时间偏差误判) - 更彻底的方案是加
--checksum:逐块比对校验和,不依赖时间,但会慢一点、CPU 高一点 - 如果只同步代码或文本,且确认没时区问题,
--size-only反而更快
备份到远程服务器失败,报 ssh: connect to host xxx port 22: Connection refused
这不是 rsync 的错,是 SSH 连接层不通。别急着改 rsync 参数。
先确认三点:
- 目标机器是否开了
sshd?运行systemctl is-active sshd看是不是active - 防火墙是否放行了 22 端口?
sudo ufw status或sudo iptables -L | grep :22 - 是否用错了地址?比如把内网 IP 当公网用,或 DNS 没解析——直接
ping或nc -zv hostname 22测试连通性
想排除临时文件和日志,但 --exclude 不生效?注意路径写法和顺序
rsync 的 --exclude 是按命令行从左到右匹配的,而且模式匹配的是“相对于源路径”的相对路径。
比如你执行:rsync -av --exclude='*.log' /var/www/ user@backup:/backup/,那 *.log 匹配的是 /var/www/ 下的 *.log,不会影响 /var/www/logs/app.log。
要排除所有层级的日志文件,得写成:
-
--exclude='**/*.log'(需要 rsync ≥ 3.1.0) - 或者更兼容的写法:
--exclude='*.log' --exclude='logs/' --exclude='.tmp' - 排除规则必须放在源路径 之前,否则会被忽略
--exclude-from=excludes.txt,方便复用和 review。
每天定时备份,crontab 里 rsync 报 Permission denied (publickey)
cron 环境变量和你终端不一样,特别是 $HOME 和 SSH_AUTH_SOCK,所以交互式能用的密钥,在 cron 里常失效。
最稳的做法:
- 用
-e "ssh -i /path/to/id_rsa"显式指定私钥路径,不要依赖~/.ssh/config - 确保私钥权限是
600,且属主是运行 cron 的用户(ls -l /path/to/id_rsa看一眼) - 测试前先用
sudo -u username bash -c 'ssh -i /path/to/id_rsa user@host ls'模拟 cron 环境
真正难的不是写对 rsync 命令,而是每次备份后花 10 秒手动 ls -lR 看一眼关键目录,或加个 --dry-run 先跑一遍。没人检查的备份,和没备份一样。










