如何让rsync删除已从源文件夹中删除的文件?

我最近设置了一个运行Ubuntu服务器的机器来托管游戏服务器。我为每个游戏服务器安装了一个备份插件,它会在机器上的特定文件夹中频繁创建游戏世界文件的备份。我还通过使用带有"-a"选项的rsync命令,在每晚自动将这些备份复制到我的Dropbox文件夹中,建立了一个cron任务。
几个月后,我的Dropbox帐户达到了存储限制,我意识到无法保留这么多备份,所以我配置了游戏服务器备份插件,不再保留那么多备份,然后等待几天看看是否像预定的一样删除旧备份。备份插件最终完成了其工作并删除了较旧的备份,因此我期望rsync cron任务随后也会从我的Dropbox文件夹中删除较旧的备份,以使其与源文件夹匹配,但实际未能如此。因此,我有几个问题:
默认情况下,rsync 只会将已添加到源文件夹的文件添加到目标文件夹,并且只会将在源文件夹中已更改的文件更改,但不会删除从源文件夹中删除的文件。
如果是这种情况,那么如何让 rsync 实现这一点呢?我希望目标文件夹完全反映源文件夹的内容,这意味着删除源文件夹中已删除的任何文件。
rsync 的手册页面中列出了一些选项,可能可以解决这个问题,但由于我对其不熟悉。

1请参阅以下其他StackExchanges上的相关重要考虑事项:https://unix.stackexchange.com/questions/18564/asking-rsync-to-delete-files-on-the-receiving-side-that-dont-exist-on-the-sendi,https://superuser.com/questions/156664/what-are-the-differences-between-the-rsync-delete-options - GDP2
6个回答

要删除目标中的文件,请在命令中添加--delete选项。例如:
rsync -avh source/ dest/ --delete

NB: -avh 是用于 --archive --verbose --human-readable

1也许使用“-aqr”代替也是一个好主意 :) - Subhamoy S.
52请确保源目录是一个有效的目录。使用 source/* dest/ 的方式是无法正常工作的。 - Tom Saleeba
8我发现使用 --delete--delete-after 选项时,由于一些错误导致无法删除事件:"遇到 IO 错误 -- 跳过文件删除"。为了解决这个问题,请添加 --ignore-errors 选项,并单独调试这些错误。 - MHT
33运行得非常完美!尽管它正常工作,但我强烈建议在运行rsync之前,特别是涉及到像这样的选项(--delete)时,始终使用-n, --dry-run选项。这将避免任何可能的麻烦 :). - ivanleoncz
3@TheBicentennialMan -a 意味着 -r - x-yuri
2@oemb1905伙计,你的心情是好的,但这是地球,人类深入挖掘你的旗帜"-avWeqr"是不对的:
  • 使用了vq,这是冗长的,被安静和不合理取消了。
  • a-rlptgoD的速记...因此你第二次使用r是多余的。
  • e也被使用了两次。 总结:根据我的理解,你的使用"-avWeqr"等同于-aW
- Williams
@Williams 是的,正确的命令应该是rsync -av --delete -e 'ssh -p 59333 -i /home/user/.ssh/id_rsa' /home/source/ user@x.x.x.x:/home/destination/ ... W 是可选的,根据个人需求会有所不同 ...(删除了旧评论以防止他人使用)... - oemb1905
@MHT 使用这个而不调试错误是否安全?因为在我的情况下,通常是一些我无法修复的问题,比如系统写入我无法操作但又不关心的文件。 - Michael
使用--delete选项与多个源是否安全? - Jonathan
是的,安全的。只会影响目标@Jonathan..下次查看帮助/手册文件。> man rsync ==== "--delete 从目标目录中删除多余的文件" ---- 它并没有说'从源目录(s)中删除'. - B. Shea
如果我在选项--files-from =$MY_SYNCFILE后面使用--delete,那么它不起作用,rsync不会删除不在$MY_SYNCFILE中的文件。 - Trung Nguyen

rsync命令在使用某些选项delete时不会删除任何文件。因此,如果源中添加了任何文件或文件夹,它们将被同步到目标位置而不会被删除。
我建议您使用rsync来备份源文件,并使用find ... rm来按时间或文件大小删除文件。
rsync [options] SOURCE TARGET
find TARGET -maxdepth 1 -type f -mtime +60 -exec rm -f {} \;

上述代码块会从源文件中创建一个备份,然后删除所有最后修改时间超过2个月的文件。
更新:
我发现“delete”选项只适用于目标文件,如果某些文件从源文件中被删除,“rsync --delete”会将它们从目标文件中删除。而根据其手册中提到的“delete”选项通过“after”和“before”来实现。
--delete-before         receiver deletes before transfer, not during

这意味着:
1. rsync将从目标中删除在源中已移除的文件。 2. rsync开始同步文件。
--delete-after          receiver deletes after transfer, not during

意思是:
1. rsync开始同步文件。 2. rsync在同步后从目标位置删除源位置已删除的文件。
注意:`--delete-{before/after}`选项只在目标位置实现。

1谢谢回复!你是指rsync的“删除”选项吗?为什么我不能只使用rsync的“删除”选项呢? - user254251
@user254251,如果你使用delete选项,rsync命令会立即删除文件。但在这种情况下,可能会有更多时间出现错误。 - shgnInc
如果我理解正确的话,你是说我应该将删除任务与rsync任务分开以避免错误。不过,我有一个问题。rsync的手册页面列出了一些选项,看起来可以通过在复制任务之前或之后运行来实现分离删除任务的目的。例如,我看到了两个名为--delete-before和--delete-after的选项。使用这些选项的rsync是否会产生与你描述的方法相同的效果?我已经阅读了手册页面上每个选项的完整描述,但其中有些信息我不太理解。 - user254251
@user254251,回答已更新。我不知道在rsync中是否有一种按时间限制从目标删除文件的方法。 - shgnInc
谢谢!那么你认为如果我只是使用"--delete-before"选项,我就能避免错误吗?我没有指定超时时间,所以如果rsync的删除阶段延迟了传输阶段,我不用担心。rsync每天运行一次,在下一次同步之前有足够的时间来同步备份文件,所以我不需要限制同步的时间。 - user254251
这张海报是错误的 - 为什么有这么多赞,当至少有两个正确答案呢? - oemb1905
@oemb1905,这里没有选定的答案,而且这个回答包含更多的细节。你可以喜欢或不喜欢它。 - shgnInc
@shgnInc 是的,我确实这样做了...但是让过路人知道某些事情不正确也很重要。 - oemb1905
具体来说,你的整个开头段落完全不准确。 - oemb1905

命令
$ rsync -avhn --delete local/ remote/

它会注意始终将本地所做的更改同步到远程。这意味着它会注意同步本地和远程,以便:
1. 在本地添加的文件会被添加到远程。 2. 从本地删除的文件会从远程删除。 3. 在远程添加的文件会被删除。 4. 从远程删除的文件如果存在,则会从本地恢复,否则会被忽略。
参数解释如下:
- -a 归档模式 - -v 增加详细程度 - -h 以人类可读的格式输出数字 - -n 模拟运行,不进行任何更改。 始终在最初使用此标志以防止数据丢失。当您满意时,请将其删除。
让结果来证明一切:
  • 创建2个目录

    $ mkdir local/ remote/
    
  • 在这些目录中创建文件

    $ touch local/local_only remote/remote_only local/exists_locally_and_remotely remote/exists_locally_and_remotely`
    
  • 查看已创建的内容(在rsync之前):

    $ ls local/ remote/ 
    
    local/:
    exists_locally_and_remotely  local_only
    
    remote/:
    exists_locally_and_remotely  remote_only
    
  • 调用rsync:

    $ rsync -avh --delete local/ remote/
    sending incremental file list
    deleting remote_only
    local_only
    
    sent 160 bytes  received 50 bytes  420.00 bytes/sec
    total size is 0  speedup is 0.00
    
  • 查看结果(在rsync之后):

    $ ls local/ remote/ 
    
    local/:
    exists_locally_and_remotely  local_only
    
    remote/:
    exists_locally_and_remotely  local_only
    
如您所见,文件remote/remote_only已被删除,文件local/local_only已被同步

这对我来说也可以,除非目的地真的很偏远。在这种情况下,会发送 local_only,但不会删除 remote_only。在我的测试中,我将本地主机上的 remote 目录进行 tar 打包,然后通过 scp 将其传输到 otherhost,在那里解压缩,并尝试使用 rsync -avh --delete local/ otherhost:$(pwd)/remote/ 进行同步。 - Jim

这个命令将复制增量数据并与远程服务器保持同步。
  1. 它只会复制增量数据。
  2. 如果源数据被删除,它也会将其删除。
  3. 如果目标地点的数据被删除,它会再次从源地点复制。
  4. 基本上,这个命令将保持两个环境的同步。

rsync -avWe ssh --delete-before (源地点) root@localhost:(目标地点) rsync -avW --delete-before -e ssh (源地点) root@localhost:(目标地点)

示例:

rsync -avWe ssh --delete-before /data root@192.168.254.254:/backup
rsync -avW --delete-before -e ssh /data root@192.168.254.254:/backup

2我认为-W使得它不仅复制增量数据,而且总是复制整个文件。 - Tulains Córdova
我执行这个命令时遇到了以下错误:rsync: Failed to exec --delete-before: No such file or directory (2) - Jeff Tian

如果在rsync同步过程中出现任何错误,即使您使用了--delete、--delete-after或--delete-before选项,rsync也不会正确删除应该删除的文件。
这就是为什么解决rsync错误很重要的原因。
我的大部分错误都是由于在与非Linux文件系统同步时使用--perms选项造成的。当我将--perms替换为--no-perms时,这些错误消失了,然后删除操作正常工作。
当您从Linux文件系统同步到另一个Linux文件系统时,--perms是可以的,但如果您从Linux同步到非Linux文件系统(如NTFS、FAT),--perms会导致错误,因为rsync无法在非Linux文件系统上设置Linux权限。再次强调,错误=无法删除。
当同步到非Linux分区时,我使用--no-perms来避免那些破坏--delete、--delete-after或--delete-before的错误。
如果你在那之后仍然遇到错误,并且无法弄清楚如何解决这些错误,你可以运行一个专门用于删除不同步文件的命令。
sudo rsync -r --delete --existing --ignore-existing --ignore-errors --progress /path/to/source/ /path/to/destination

上述命令将删除不同步的内容,但不会同步任何文件。因此,在执行此操作后,您应该再次进行同步。该命令基于answer,只是我还添加了--ignore-errors参数,这样即使存在错误也会执行删除操作。

2谢谢这个建议!我是5年前提问的原作者。真高兴你发表了这个帖子,因为我计划在近期将同步设置到NTFS驱动器上,而且我可能会遇到权限错误,因为我打算使用rsync的"-a"选项,该选项会同步权限(以及其他内容)。所以我在我的笔记中添加了"--no-perms"。现在我计划使用rsync -a --no-perms --delete-before命令。我有一个问题:--delete-before不是通过在同步之前运行删除操作来避免文件删除问题吗?我以为这就是它的目的。 - user254251
@user254251 - 我不确定。我猜这取决于真正的“删除之前”多早。如果在删除开始之前出现错误,那就完蛋了。我给你的建议是尽量避免使用NTFS,除非你喜欢屁股上的刺痛 :). NTFS到NTFS之间可以正常运行。NTFS到Linix也没问题。要避免将“Linux文件系统”转换为“非Linux文件系统”,这样做会很麻烦,无法确保删除操作正常。虽然你可以实现这个目标,但我认为与其费事不如直接将目标驱动器格式化为EXT4。 - Lonnie Best

“-delete”标志必须出现在您的/source和/destination之后。 所以是这样的。
rsync -rvpthE --progress /Volumes/EOS_DIGITAL/DCIM/ /Users/mitchellg/Desktop/files -delete

选项有:
- -r 递归 - -v 详细(打印到屏幕) - -p 权限 - -t 时间(使用时间而不是校验和 'c') - -h 可读性强 - -E 扩展信息(.Mac 上的颜色标签)

3你确定在--delete前面不需要两个--吗?为什么你认为这个删除选项的位置必须出现在目录之后? - PeterCo