rsync,删除接收方已在发送方删除的文件。(但不要删除所有内容)


9

我想使用rsync来...

  • 删除在接收方也已在发送方删除的文件
  • 不删除接收方rsynced目录中的其他文件

例如,假设我有一个目录local-src

之前: local-src本地包含...

a.txt
b.txt
c.txt

我要同步到的内容的远程目录local-src称为remote-src

之前: remote-src远程包含...

a.txt
b.txt
c.txt
d.txt
README.md

假设我删除了一些文件local-src

局部删除后: local-src本地包含...

c.txt

如何使用rsync来确保在源位置删除的文件也可以在目标位置删除,而又不能删除在目标位置的其他文件。例如,我要在目的地放置以下物品:

本地删除后: remote-src远程包含...

c.txt
d.txt
README.md

也就是说,a.txt并且b.txt被远程删除为好,但d.txtREADME.txt被单独留在家中。

有什么办法可以使用rsync做到这一点?

编辑:判决似乎是使用rsync这可能是不可能的。有人问我为什么需要这个,所以来说明我的用例:

假设我有一个Web服务器。在该Web服务器上,我有一堆目录,比方说,我有一个目录A以及public_html从中提供网站的目录。假设我有一些自动化过程,可以在directory中生成文件A。我想rsync的(或使用其他工具同步)产生或文件更新Apublic_html目录,而不删除其他任意文件,可能是内public_html。我当然不希望rsync意外删除我的网站。

如果rsync不是完成这项工作的工具,那么其他人知道我该怎么做吗?


2
重新阅读您的问题后,我认为这是不可能的,rsync因为无法知道远程文件夹中已有哪些文件。您可能需要查找其他工具。
Spack

rsync不允许您这样做,但是如果每次删除文件时都覆盖整个目录,则可以使它们保持同步,而不仅仅是一个建议。
Aadi Droid

1
我猜您已经想到了这一点,但是您是否不能仅将这些文件放在子目录(或其他位置)中并从public_html引用它们?这样一来,您就可以轻松,明确地同步一个目录,而不会影响Web服务器文件系统其他部分中的文件。
MattJenko 2014年

Answers:


2

您想做的事是合理的,但单靠rsync自己做是不可行的。所以答案是否定的

原因很简单:rsync没有保存每个目录中的内容的历史记录,也无法知道需要删除哪些内容和不需要删除哪些内容。并非没有其他支持。

您应该问自己为什么要这样做rsync并使其更加清晰。还有其他使用librsync1.so更智能的程序。


有了rsync本质上不需要的宽松约束,您可以看一下rdiff-backup

mkdir a
touch a/xx
touch a/yy
rdiff-backup a b
ls b 

显示xxyyb

touch b/zz
rm a/xx
rdiff-backup a b

显示xxzzbrdiff-backup还保留一个目录rdiff-backup-datab以便您可以回滚所有更改,您应该使用rdiff-backup命令定期清除此更改。(该示例与本地文件一起使用,以显示目标中的额外数据不会被删除,但是rdiff-backup也可以通过网络工作)。


另一种选择是设置一些分布式修订控制系统(Mercurial,Bazaar,Git)。例如,您可以使用一个脚本(我使用一个Makefile),该脚本将所有更改推送到服务器,然后在那里更新检出的文件,而忽略远程服务器上的任何其他文件(但是不受修订控制)。

在服务器上,您可以执行以下操作:

hg init
hg add file_list_excluding_that_should_not_should_be_deleted_if_not_on_client
hg commit -m "initial setup"

在客户端上:

hg clone ssh://username@server/dir_to_repository

现在,如果您在客户端上删除文件并执行以下操作:

hg commit -m "removed file"
ssh username@server "cd dir_to_repository; hg update --clean"

您删除的文件已在服务器上删除,但是其他任何数据(未添加到存储库)都不会被删除。


我可以接受rsync不会这样做。但是我不同意使用rsync这是不可能的-如果rsync在发送方知道哪些文件已被删除,为什么它不能将该信息发送到diff的接收方?比较新鲜度之后,我看不到为什么接收方不能只删除在diff中指示要删除的文件,而不删除目录中的其他所有文件。对我来说,删除目录中的每个其他文件(在源文件中未删除)都是无害的。
Heather Miller

无论如何,我需要这样做的原因如下。我有一个目录,我们称它为目录,该目录A中的某些过程是自动执行的,并且在那里会自动生成文件。我有一个Web服务器,我希望将其中的文件A同步到public_html该Web服务器的目录中,当然不要删除public_html该Web服务器文件夹中的其他所有内容。如果有人对使用其他工具实现此目标有任何想法,那就太受欢迎了。我将更新我的问题以反映这一点。
希瑟·米勒

为了澄清我的第一条评论,我应该说:“我不同意使用rsync之类的工具来完成类似的事情是不可能的”。凭直觉,这似乎很难实现(除非我遗漏了一些东西)。
希瑟·米勒

嗯。。好。我想我现在知道了-rsync如何知道local-src目录中何时删除了某些内容,而又没有任何进程监视该目录中的更改。也许这很难。
希瑟·米勒

就像我写的那样,@ HeatherMiller您的请求是合理的,但rsync不是工具。请意识到,syncin rsync来自同步,而这并非您要做的。在开发中rsync,重点一直放在有效(最小化)数据传输上。诸如rdiff-backup(和可能的cvsup)之类的其他工具已经使用了它的技术,但是在它的基础上增加了附加功能。
Anthon

1

我认为如果没有明确排除接收方文件作为rsync命令的一部分,这是不可能的。有关rsync的信息,请参见手册页部分:“ PER-DIRECTORY RULES AND DELETE”。

如果没有删除选项,则按目录规则仅与发送方相关,因此您可以随意排除合并文件本身而不会影响传输。为了使这一过程变得容易,“ e”修饰符为您添加了此排除项,如以下两个等效命令所示:

          rsync -av --filter=': .excl' --exclude=.excl host:src/dir /dest
          rsync -av --filter=':e .excl' host:src/dir /dest

但是,如果要在接收方进行删除,并且要从删除中排除某些文件,则需要确保接收方知道要排除哪些文件。最简单的方法是在传输中包括按目录合并文件,并使用--delete-after,因为这可以确保接收方在尝试删除任何内容之前获得与发送方相同的排除规则:

          rsync -avF --delete-after host:src/dir /dest

但是,如果合并文件不是传输的一部分,则需要指定一些全局排除规则(即在命令行上指定),或者需要在目录上维护自己的按目录合并文件。接收方。第一个示例是这样的(假设远程.rules文件排除自身):

   rsync -av --filter=’: .rules’ --filter=’. /my/extra.rules’
      --delete host:src/dir /dest

在上面的示例中,extra.rules文件可能会影响传输的双方,但是(在发送方)规则是从.rules文件合并的规则的从属,因为它们是在按目录合并规则之后指定的。

在最后一个示例中,远程端从传输中排除了.rsync-filter文件,但是我们想使用我们自己的.rsync-filter文件来控制在接收端删除的内容。为此,我们必须明确排除按目录合并的文件(这样就不会删除它们),然后将规则放入本地文件中,以控制不应删除的其他内容。像以下命令之一:

       rsync -av --filter=':e /.rsync-filter' --delete \
           host:src/dir /dest
       rsync -avFF --delete host:src/dir /dest

0

如果我正确理解,--exclude那么您可能正在寻找:

$ ls src dst
dst:
a.txt  b.txt  c.txt  d.txt  README.md

src:
c.txt
$ rsync --update --delete --recursive --exclude="d.txt" --exclude="README.md" src/ dst
$ ls src dst
dst:
c.txt  d.txt  README.md

src:
c.txt

好吧,不。我不想手动列出所有我想排除的文件。我只想rsync仅删除在源上删除的文件-我不必在源上知道目标的同一目录中还存在哪些其他文件。
希瑟·米勒

0

我对此有一个答案。我认为这有效。它对我有用。首先,您必须将rsync远程文件转换为本地文件。然后本地包含所有文件。

sudo rsync -r -a -v --delete /root@xx.xx.xx.xx:/remote_dir/ /local_dir/

现在在本地

a.txt
b.txt
c.txt
d.txt
README.md

然后,您可以删除文件或执行任何所需的操作(在本地)。在您的问题中,您删除了这些文件。

删除的文件

a.txt
b.txt

之后,您可以将rsync本地文件发送到远程端,然后双方具有相同的文件。

sudo rsync -r -a -v --delete /local_dir/ root@xx.xx.xx.xx:/remote_dir/

它给

c.txt
d.txt
README.md

(通过使用--delete,它会删除与本地不匹配的其他远程文件)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.