Вопрос или проблема
Я копирую много изменившихся файлов с одного сервера на другой с помощью rsync. Я знаю, что могу использовать опцию -n
для выполнения пробного запуска, чтобы увидеть, какие файлы были изменены. Однако возможно ли сделать так, чтобы rsync выводил различия в содержимом файлов, которые изменились? Я хотел бы увидеть, что происходит, прежде чем выполнять копирование. Что-то, что я могу сохранить в файл и применить с помощью diff(1) позже?
Может быть, есть лучший способ, но это может сработать, хотя и не очень эффективно:
rsync -vrn / dest:/ > ~/file_list
Затем отредактируйте тест, чтобы удалить статистику, затем:
while read file; do
diff $file <(ssh dest "cat $file")
done < ~/edited_file_list
Другой вариант:
Вы также можете рассмотреть возможность монтирования файловой системы с помощью чего-то вроде sshfs/fuse, а затем просто использовать diff.
Чтобы создать патч:
rsync -arv --only-write-batch=patch new/ old/
Чтобы применить его:
rsync -arv --read-batch=patch dir/
или использовать автоматически сгенерированный скрипт:
./patch.sh
Источники:
rsync не может сделать это изначально, но если есть возможность использовать unison, вы можете создать различия в формате.
Это невозможно сделать изначально, потому что rsync заботится только о бинарных различиях между файлами.
Вы можете попытаться написать скрипт, использующий вывод rsync. Но это будет не очень элегантно.
Я верю, что это возможно изначально с помощью Unison.
Почему бы не использовать что-то вроде diff (для текстовых файлов) или xdelta (для двоичных файлов) для генерации различий? Зачем вам конкретно что-то из rsync?
Чтобы расширить ответ Кайла, это автоматизирует процесс. Обратите внимание, что это совершенно непроверено, вероятно, довольно хрупко и может удалить ваш компьютер и убить вашу собаку.
#!/bin/bash
REMOTE=${1?Отсутствует удаленный путь}
LOCAL=${2?Отсутствует локальный путь}
# Убираем завершающий слэш, так как мы добавим его как разделитель позже
REMOTE=${REMOTE%/}
LOCAL=${LOCAL%/}
# Разбиваем на части
RHOST=${REMOTE%:*}
RPATH=${REMOTE#*:}
while read FILE; do
diff -u ${LOCAL}/${FILE} <(ssh $RHOST "cat ${RPATH}/${FILE}")
done < <(rsync -vrn $REMOTE/ $LOCAL/ | sed '1d;/^$/q')
Алгоритм rsync работает, сравнивая бинарные участки файла. Такие бинарные различия не предназначены для печати. Есть команда под названием rdiff, которая использует алгоритм rsync для генерации бинарных различий, но я не думаю, что это будет полезно для того, что вы описываете; она обычно используется для реализации инкрементных резервных копий.
Существует способ сделать это, используя опцию --compare-dest=DIR
в rsync
.
Это может выполнить разреженную синхронизацию (перенос только изменившихся файлов) в временный каталог, с которым вы можете сравнить на удаленном сервере.
Это безопасно оставляет реальные целевые файлы нетронутыми.
Пример:
rsync --recursive --checksum --compare-dest=../dest-actual/ /path/to/source/ remote-server:/path/to/dest-for-diffing/
ssh remote-server
cd /path/to/
diff --recursive --unified=4 dest-actual/ dest-for-diffing/ > ~/changes.patch
vim ~/changes.patch
Вы можете передать diff
через grep -vE '^Only in '
, чтобы пропустить шум от неизмененных файлов.
Обратите внимание, что это, как и другие решения здесь, не обрабатывает файлы, которые были удалены локально, но все еще существуют на удаленном сервере.
Ответ или решение
Как использовать rsync для генерации патчей вместо копирования файлов
Вам нужно скопировать измененные файлы с одного сервера на другой с помощью rsync
, и вы хотите изучить различия в содержимом файлов перед их копированием? Хотя rsync
сам по себе не создает патчи в формате diff
, есть несколько способов достичь желаемого результата, используя его функционал вместе с другими командами и подходами.
1. Использование параметра --only-write-batch
Один из наиболее простых способов создать патч с изменениями — использовать опцию --only-write-batch
. Эта команда записывает все различия в файлы, которые потом можно использовать для синхронизации в дальнейшем.
Команда для создания патча:
rsync -arv --only-write-batch=patch new/ old/
Применение созданного патча:
rsync -arv --read-batch=patch dir/
Или вы можете использовать автоматически сгенерированный скрипт:
./patch.sh
2. Использование diff
и временной директории
Вы также можете использовать временную директорию для сравнения файлов. Это безопасный метод, позволяющий оставить оригинальные файлы без изменений.
Пример:
rsync --recursive --checksum --compare-dest=../dest-actual/ /path/to/source/ remote-server:/path/to/dest-for-diffing/
ssh remote-server
cd /path/to/
diff --recursive --unified=4 dest-actual/ dest-for-diffing/ > ~/changes.patch
vim ~/changes.patch
В этом примере мы используем --compare-dest
, чтобы сравнить файлы с оригинальными версиями в другой директории. Затем с помощью команды diff
мы можем узнать, какие изменения произошли, и сохранить их в файл changes.patch
.
3. Объединение с ssh
и diff
Если вам необходимо создать дамп содержимого файлов, вы можете запустить цикл, который будет сравнивать файлы локально и на удаленном сервере.
Пример скрипта:
#!/bin/bash
REMOTE=${1?Не указано удаленное хранилище}
LOCAL=${2?Не указан локальный путь}
REMOTE=${REMOTE%/}
LOCAL=${LOCAL%/}
RHOST=${REMOTE%:*}
RPATH=${REMOTE#*:}
while read FILE; do
diff -u ${LOCAL}/${FILE} <(ssh $RHOST "cat ${RPATH}/${FILE}")
done < <(rsync -vrn $REMOTE/ $LOCAL/ | sed '1d;/^$/q')
Этот скрипт запускает rsync
в режиме "тестового запуска", извлекая список измененных файлов и сравнивая каждый файл локально с его удаленной версией с помощью команды diff
.
4. Использование других инструментов
Если вам нужны патчи в формате diff
, а не бинарные отличия, вы можете рассмотреть возможность использования других инструментов, таких как unison
или rdiff
. Обе программы способны генерировать удобные для анализа различия, и могут быть более подходящими для ваших целей.
Заключение
Хотя rsync
сам по себе не может создать патч в формате diff
, существуют различные способы для реализации этой задачи, комбинируя его с другими инструментами и подходами. Способы, описанные выше, позволяют вам получить отчеты о различиях между файлами, что поможет вам лучше управлять процессом передачи данных и минимизировать риск ненужного изменения или потери данных.