Зачем нужен пробный запуск
Синхронизация папок кажется простой, пока не появляется неверный путь или лишний ключ. Тогда rsync послушно скопирует не то и не туда, а при ключе --delete ещё и удалит файлы в целевой папке. Откат в такой ситуации возможен не всегда, а без резервной копии часто невозможен. Поэтому у rsync есть режим репетиции: те же вычисления, тот же сравнительный проход по двум деревьям, но без записи на диск.
Пробный режим включается ключом --dry-run или его короткой формой -n. В нём rsync сравнивает источник и приёмник, определяет, какие файлы отличаются, и печатает план. Сами файлы не копируются, не удаляются и не переименовываются. Это позволяет проверить три вещи: правильно ли выбраны папки, не слишком ли широк список и нет ли в нём строк об удалении.
Практика простая: любую новую команду rsync, особенно с --delete, сначала запускают с -n. Команда для учебного эксперимента выглядит так: rsync -avn ~/rsync-demo/src/ ~/rsync-demo/dst/. Здесь -a включает режим архива (рекурсия с сохранением прав, времени изменения, символических ссылок; владельца и группу rsync сохраняет только при достаточных правах, обычно от root), -v делает вывод подробным, а -n отключает реальные изменения.
Пробный запуск показывает план, но не заменяет резервную копию: между репетицией и настоящим запуском данные могут измениться.
Готовим тестовую пару папок
Не начинайте с боевых данных. Создайте две папки, которые можно потерять без последствий, и наполните их файлами так, чтобы в них были и совпадающие, и разные элементы. Например:
- mkdir -p ~/rsync-demo/src ~/rsync-demo/dst — создаёт обе папки.
- echo one > ~/rsync-demo/src/a.txt и echo two > ~/rsync-demo/src/b.txt — два файла в источнике.
- cp -p ~/rsync-demo/src/a.txt ~/rsync-demo/dst/ — один файл уже есть в приёмнике; ключ -p сохраняет время изменения, иначе у копии оно будет другим, и rsync включит файл в план.
- echo old > ~/rsync-demo/dst/extra.txt — файл, которого нет в источнике.
Теперь запустите rsync -avn ~/rsync-demo/src/ ~/rsync-demo/dst/ и посмотрите вывод. В списке должен появиться b.txt как файл к передаче. Файла a.txt в списке быть не должно, пока не изменятся его размер или время, а extra.txt не тронут, потому что ключа --delete нет. Строка со знаком «./» (сам каталог) в списке может появиться или нет, в зависимости от версии и времени изменения каталога.
Обратите внимание на косую черту в конце первого пути. Она меняет смысл команды: с ней копируется содержимое папки, без неё — сама папка целиком. Этот нюанс разобран в отдельной статье, ссылка на неё есть среди связанных.
Только убедившись, что тестовый сценарий понятен, переносите привычку на реальные папки.
Как читать вывод: -v и -i
Обычный подробный вывод -v просто перечисляет имена файлов, которые были бы переданы, и в конце печатает короткую сводку. Этого хватает для небольших задач. Но когда нужно понять причину, по которой файл попал в план, пригоден ключ -i (--itemize-changes): перед каждым именем появляется строка из одиннадцати символов, в которой каждая позиция описывает один признак.
Для разбора достаточно нескольких вариантов, которые приводятся в справке rsync:
| Начало строки | Как понимать |
|---|---|
| >f+++++++++ | новый файл, которого в приёмнике ещё нет |
| >f.st...... | файл есть, но отличаются размер (s) и время изменения (t) |
| cd+++++++++ | будет создан новый каталог |
| *deleting | файл будет удалён из приёмника (при --delete) |
Первый символ показывает направление: знак больше означает передачу в приёмник. Второй описывает тип: f — файл, d — каталог. Точки на остальных позициях означают, что признак не отличается. Полный перечень позиций смотрите в man rsync, раздел про --itemize-changes.
Если вывод слишком длинный, пропустите его через less или посчитайте строки через wc -l, как показано в соседних материалах. Для сводки по объёму добавьте --stats, она печатает итоги по числу и размеру файлов.
Что пробный режим не проверяет
Репетиция показывает, какие файлы rsync собирается тронуть, но у неё есть границы. Полезно знать их заранее, чтобы не воспринимать «чистый» вывод как полную гарантию.
- Свободное место. Пробный запуск не проверяет, хватит ли его в приёмнике. Сравните объём по строке --stats с выводом df -h.
- Права доступа. Файл может попасть в план, а при настоящей записи упасть с ошибкой доступа, если у вас нет прав на папку назначения.
- Изменения между запусками. Список построен на момент репетиции. Если за это время файлы менялись, итог окажется другим.
- Сетевые сбои. При копировании на другую машину по SSH обрыв связи во время реальной передачи данных пробный режим не воспроизводит.
Ещё один нюанс: сравнение по умолчанию идёт по размеру и времени изменения. Если файл заменили на другой того же размера с тем же временем, rsync его пропустит. Ключ -c заставляет сравнивать по контрольным суммам, но это заметно дольше, поэтому включайте его осознанно.
Версии rsync на Linux и macOS могут различаться: в macOS в разных выпусках поставляется разная реализация, а формат вывода и набор ключей зависят от версии. Проверьте свою командой rsync --version и ориентируйтесь на rsync --help или man rsync.
Порядок действий перед боевым запуском
Соберите собственный короткий регламент, чтобы синхронизация не превращалась в лотерею. Один из вариантов выглядит так.
- Проверьте пути глазами: echo с теми же путями выведет их без выполнения.
- Запустите команду с -avn и, если нужны причины, добавьте -i.
- Найдите в выводе строки deleting. Если вы не планировали удаление, проверьте, не попал ли в команду ключ --delete.
- Сравните количество и размер переносимого по --stats с ожиданиями.
- Только после этого повторите ту же команду без -n.
После настоящего запуска повторите ту же строку с -n ещё раз: если синхронизация прошла полностью, список к передаче обычно оказывается пустым (максимум строка про сам каталог), а это удобная проверка результата. Для регулярных задач сохраните команду в скрипт и храните пробный вариант рядом, меняя один ключ.
Для копирования между машинами по сети есть scp, но он не сравнивает деревья и пробного режима у него нет. А на Windows аналогичную роль играет ключ /L у robocopy, он описан в связанной странице.