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.txtи README.txtостаются одни.

Есть ли способ достичь этого с помощью rsync?

РЕДАКТИРОВАТЬ: кажется, вердикт, что это может быть невозможно с rsync. Меня спросили, зачем мне это нужно, чтобы проиллюстрировать мой вариант использования:

Допустим, у меня есть веб-сервер. На этом веб-сервере у меня есть несколько каталогов, скажем, у меня есть каталог Aи public_htmlкаталог, из которого обслуживается мой сайт. Допустим, у меня есть какой-то автоматизированный процесс, который создает файлы в каталоге A. Я хотел бы Rsync (или синхронизация с помощью какого - либо другого инструмента) файлы , созданных или обновленных в Aв public_htmlкаталог, не удаляя другие произвольные файлы , которые могут быть в пределах public_html. Я, конечно, не хочу, чтобы rsync случайно удалил мой сайт.

Если rsync не является инструментом для этой работы, знает ли кто-то еще, как я могу это сделать?

Хизер Миллер
источник
2
Перечитав ваш вопрос, я не думаю, что это возможно, rsyncпоскольку нет способа узнать, какие файлы уже находятся в удаленной папке. Вам может понадобиться найти другой инструмент.
Spack
rsync не позволит вам сделать это, но если вы удаляете весь каталог каждый раз, когда удаляете файлы, вы можете поддерживать их синхронизацию, а не решение, а просто предложение.
Аади Дроид
1
Я предполагаю, что вы уже подумали об этом, но не могли бы вы просто поместить эти файлы в подкаталог (или где-то еще) и ссылаться на них из public_html? Таким образом, у вас есть один каталог, который легко и явно синхронизируется, не затрагивая файлы в других частях файловой системы веб-сервера.
MattJenko

Ответы:

2

То, что вы хотите сделать, разумно, но использовать его rsyncдля этого не стоит. Так что ответ - нет .

Причина проста: не rsyncхранит историю того, что было в каждом каталоге, и не знает, что нужно удалить, а что нет. Не без дополнительной поддержки.

Вы должны спросить себя, почему вы хотели бы сделать это rsyncи сделать это более ясным. Есть другие программы, которые используют librsync1.soболее интеллектуальные.


С ослабленными ограничениями, которые вам сами по себе не нужны rsync, вы можете взглянуть на rdiff-backup :

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

Это показывает xxи yyв b.

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

Это показывает xxи zzв b. rdiff-backupтакже хранит каталог rdiff-backup-dataв bтак что вы можете откатить изменения, вы должны очистить это на регулярной основе с использованием rdiff-backupкоманд. (Пример с локальными файлами, показывающими, что дополнительные данные в целевом объекте не удаляются, но rdiff-backup также работает по сети).


Другой альтернативой является настройка некоторой распределенной системы контроля версий (Mercurial, Bazaar, Git). Например, в случае с Mercurial у вас может быть скрипт (для этого я использую 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, без удаления всего остального в каталоге. Удаление любого другого (не восстановленного в источнике) невинного файла в каталоге кажется мне неоправданным.
Хизер Миллер
В любом случае, причина, по которой мне это нужно, заключается в следующем. У меня есть каталог, давайте назовем его A, где какой-то процесс автоматизирован, и там автоматически создаются файлы. У меня есть веб-сервер, и я хотел бы, чтобы файлы внутри него Aбыли синхронизированы с public_htmlкаталогом веб-сервера, разумеется, без удаления всего остального в public_htmlпапке веб-сервера. Если у кого-то есть идеи для достижения этого с помощью другого инструмента, это будет более чем приветствоваться. Я обновлю свой вопрос, чтобы отразить это.
Хизер Миллер
Чтобы уточнить мой первый комментарий выше, я должен был сказать: «Я не согласен с тем, что что-то подобное должно быть невозможно с таким инструментом, как rsync». Интуитивно кажется, что этого не может быть слишком сложно достичь (если я что-то упустил).
Хизер Миллер
Хмм хорошо. Я думаю, что теперь вижу - как rsync может узнать, когда что-то было удалено в local-srcкаталоге, без какого-либо процесса, наблюдающего за этим каталогом на предмет изменений. Может быть, это будет сложно.
Хизер Миллер
@HeatherMiller Как я уже писал, ваш запрос обоснован, но rsyncне является инструментом. Следует понимать , что syncв rsyncпроисходит от синхронизации , и это не совсем то , что вы хотите сделать. При разработке rsyncакцент был сделан на эффективную (минимизирующую) передачу данных. Другие инструменты, такие как rdiff-backup(и, возможно, cvsup), использовали свои методы для этого, но опираются на него с дополнительными функциями.
Энтон
1

Я не думаю, что это возможно без явного исключения файлов на принимающей стороне как часть команды rsync. См. Раздел справочной страницы для rsync: «ПРАВИЛА И УДАЛЕНИЕ».

Без опции удаления правила для каждого каталога актуальны только для отправляющей стороны, поэтому вы можете свободно исключать сами файлы слияния, не влияя на передачу. Чтобы сделать это проще, модификатор '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
SLM
источник
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
Spack
источник
Ну нет. Я не хочу вручную перечислять все файлы, которые я хотел бы исключить. Я бы хотел, чтобы 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он удаляет другие файлы на удаленной стороне , которые не совпадают с локальной стороной ).

Туситха Суманадаса
источник