You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何修改rsync备份脚本以合并两个源目录到单个备份目录并保留删除同步功能?

如何修改rsync备份脚本以合并两个源目录到单个备份目录并保留删除同步功能?

嘿,这个问题我之前也碰到过!直接用两次带--delete的rsync肯定不行——第一次同步第一个磁盘后,第二次用--delete会把备份里属于第一个磁盘但第二个磁盘没有的文件删掉,完全不符合合并的需求。不过我们可以分几步来实现你的目标:既要合并两个源的内容,又要能同步删除(也就是两个源里都不存在的文件,备份里也要删掉)。

核心思路

先把两个源的内容都同步到备份目录(不删除任何东西),然后再单独处理“删除两个源都没有的文件”这个需求。具体步骤如下:

1. 先合并两个源的内容到备份目录

首先分别同步两个外部磁盘到服务器的备份目录,不要加--delete参数,这样就能把两个磁盘的内容合并到一起:

# 同步第一个磁盘
rsync -av --exclude '.*' /path/to/first/disk/ your-server:/path/to/backup

# 同步第二个磁盘
rsync -av --exclude '.*' /path/to/second/disk/ your-server:/path/to/backup

这一步完成后,备份目录里就会有两个磁盘的所有文件了,比如你例子里的A/1-5B/10-30都会存在。

2. 处理“同步删除”的需求

这一步是关键:我们需要生成一个包含两个源所有文件的列表,然后告诉rsync只保留这个列表里的文件,删掉其他的。

步骤分解:

  • 先生成两个源的所有文件的相对路径列表(要和备份目录里的路径对应):
# 创建临时文件存放文件列表
TMP_LIST="/tmp/backup_files.txt"
rm -f "$TMP_LIST"

# 提取第一个磁盘的文件相对路径,排除隐藏文件
find /path/to/first/disk -type f -not -path '*/\.*' | sed "s|^/path/to/first/disk/||" >> "$TMP_LIST"

# 提取第二个磁盘的文件相对路径,追加到列表
find /path/to/second/disk -type f -not -path '*/\.*' | sed "s|^/path/to/second/disk/||" >> "$TMP_LIST"

# 去重,避免同一个文件被重复列出
sort -u "$TMP_LIST" -o "$TMP_LIST"
  • 然后用rsync的--files-from参数指定要保留的文件,再用--delete-excluded删掉不在列表里的文件:
rsync -av --delete-excluded --delete-empty-dirs --files-from="$TMP_LIST" / your-server:/path/to/backup

这里的/是因为我们用的是相对路径,rsync会基于这个根路径去匹配列表里的文件,最终只会保留两个源里存在的文件,同时删掉那些两个源都没有的旧文件;--delete-empty-dirs还会顺便清理掉备份目录里空的文件夹(如果两个源里对应的目录都空了的话)。

整合完整脚本

把上面的步骤写成一个可执行脚本,用起来更方便:

#!/bin/bash
# 配置你的路径
SRC1="/path/to/your/first/external/disk"
SRC2="/path/to/your/second/external/disk"
SERVER="your-server-username@your-server-ip"
BACKUP_DIR="/path/to/backup/on/server"

# 第一步:同步两个源到备份目录,合并内容
rsync -av --exclude '.*' "$SRC1"/ "$SERVER:$BACKUP_DIR"
rsync -av --exclude '.*' "$SRC2"/ "$SERVER:$BACKUP_DIR"

# 第二步:生成合并后的文件列表
TMP_FILE="/tmp/combined_backup_files.txt"
rm -f "$TMP_FILE"

# 提取第一个源的文件相对路径
find "$SRC1" -type f -not -path '*/\.*' | sed "s|^$SRC1/||" >> "$TMP_FILE"
# 提取第二个源的文件相对路径
find "$SRC2" -type f -not -path '*/\.*' | sed "s|^$SRC2/||" >> "$TMP_FILE"
# 去重
sort -u "$TMP_FILE" -o "$TMP_FILE"

# 第三步:清理备份目录中两个源都不存在的文件和空目录
rsync -av --delete-excluded --delete-empty-dirs --files-from="$TMP_FILE" / "$SERVER:$BACKUP_DIR"

# 清理临时文件
rm -f "$TMP_FILE"

重要提醒

  • 测试的时候一定要加--dry-run参数!比如在rsync命令后加--dry-run,这样只会显示要执行的操作,不会真的修改文件,避免误删重要内容。
  • 确保你的rsync版本支持这些参数(大部分现代版本都没问题)。
  • 如果两个源里有同名文件,后面同步的那个(也就是第二个磁盘的文件)会覆盖第一个的——如果需要区分同名文件,你可能需要额外处理,但根据你的描述,目录结构一致,应该不会有同名文件冲突的问题。

备注:内容来源于stack exchange,提问作者Jure Merhar

火山引擎 最新活动