rsync копирует файлы и каталоги так, чтобы приёмник совпал с источником. Он сравнивает размер и время изменения и передаёт только то, что отличается, а у изменённых файлов по сети — только изменённые куски. Поэтому повторный запуск почти мгновенный. Работает локально и между машинами по SSH; на удалённой стороне тоже должен быть установлен rsync.
Синтаксис
rsync [опции] источник… приёмник
rsync [опции] источник… user@host:/путь # на удалённую машину по SSH
rsync [опции] user@host:/путь приёмник # с удалённой машины
rsync [опции] источник # без приёмника — только список файлов
Слеш в конце источника
| Команда | Результат |
|---|
rsync -a src dst/ | появится dst/src/… — копируется сам каталог |
rsync -a src/ dst/ | появится dst/… — копируется содержимое каталога |
Для каталога-источника слеш в конце приёмника ничего не меняет. А для одного файла важен: rsync -a file dst создаст файл dst, а rsync -a file dst/ — каталог dst с файлом внутри.
Что сохранять
| Опция | Что делает |
|---|
-a | режим архива = -rlptgoD: рекурсивно, ссылки, права, время, группа, владелец, устройства |
-r | только рекурсия — без прав, времени и владельцев |
-H | сохранять жёсткие ссылки (в -a не входит) |
-A / -X | сохранять ACL / расширенные атрибуты |
-L | копировать файлы вместо символических ссылок |
-k | ссылки на каталоги заменять самими каталогами |
--safe-links | пропускать ссылки, ведущие за пределы копируемого дерева |
-x | не переходить на другие файловые системы |
--chown=user:group | назначить владельца в приёмнике |
--chmod=D750,F640 | назначить права: D — каталогам, F — файлам; можно u+x, go-w |
--numeric-ids | переносить UID/GID числами, не сопоставляя имена |
--no-perms, --no-owner, --no-group | убрать отдельный пункт из -a |
Какие файлы брать
| Опция | Что делает |
|---|
--exclude='шаблон' | не копировать подходящие файлы и каталоги |
--include='шаблон' | копировать, даже если дальше есть подходящий --exclude |
--exclude-from=файл / --include-from=файл | шаблоны из файла, по одному на строку |
-F | брать правила из файлов .rsync-filter в каталогах источника |
-C | пропускать то, что обычно не нужно: .git, .svn, *.o, core и т. п. |
--files-from=список | копировать только перечисленные в файле пути (относительно источника) |
-R | сохранить в приёмнике путь источника целиком (src/a/b → dst/src/a/b) |
-m | не создавать пустые каталоги (удобно с --include/--exclude) |
--max-size=100M / --min-size=1k | пропускать файлы больше / меньше указанного |
--existing | обновлять только файлы, которые уже есть в приёмнике |
--ignore-existing | не трогать файлы, которые уже есть в приёмнике |
-u | не перезаписывать файлы, которые в приёмнике новее |
Как сравнивать
| Опция | Что делает |
|---|
| (по умолчанию) | файл одинаковый, если совпадают размер и время изменения |
-c | сравнивать по контрольной сумме — медленно, но надёжно |
--size-only | сравнивать только размер |
-I | передавать даже файлы с одинаковыми размером и временем |
--modify-window=1 | считать время одинаковым при разнице до 1 секунды (FAT, сетевые ФС) |
-W | передавать файлы целиком, без поиска изменённых кусков (быстрее локально) |
Удаление и резервные копии
| Опция | Что делает |
|---|
--delete | удалить в приёмнике файлы, которых нет в источнике |
--delete-after | удалять после передачи, а не до неё |
--delete-excluded | удалять в приёмнике и исключённые файлы |
--max-delete=N | не удалять больше N файлов (защита от ошибки, код 25) |
--remove-source-files | удалить из источника переданные файлы (перенос; каталоги остаются) |
-b | заменяемые и удаляемые файлы сохранять с суффиксом ~ |
--backup-dir=каталог | сохранять их в отдельный каталог |
--suffix=.bak | свой суффикс для резервных копий |
--link-dest=каталог | неизменённые файлы делать жёсткими ссылками на файлы в каталоге — экономные ежедневные снимки |
Передача и сеть
| Опция | Что делает |
|---|
-n (--dry-run) | ничего не менять, только показать, что будет сделано |
-z | сжимать данные при передаче по сети |
-e 'ssh -p 2222 -i ~/.ssh/key' | как подключаться к удалённой машине |
--rsync-path='sudo rsync' | какую команду запустить на удалённой стороне |
--bwlimit=10m | ограничить скорость |
-P | --partial --progress: сохранять недокачанное и показывать прогресс |
--partial | не удалять недокачанный файл — докачать при следующем запуске |
--inplace | писать прямо в файл приёмника, без временной копии |
--timeout=60 | оборвать, если 60 секунд нет обмена данными |
--mkpath | создать недостающие каталоги пути приёмника |
Вывод
| Опция | Что делает |
|---|
-v | печатать передаваемые файлы и итог |
-i | печатать для каждого файла, что именно изменилось (формат ниже) |
-h | размеры в человеческом виде |
--progress / --info=progress2 | прогресс по каждому файлу / общий прогресс |
--stats | подробная статистика в конце |
--log-file=файл | писать журнал в файл |
-q | молчать, кроме ошибок |
Строка -i выглядит как >f.st...... путь. Первый символ — что происходит: > получено, < отправлено, c создано (каталог, ссылка), . только атрибуты, *deleting — удалено. Второй — тип: f файл, d каталог, L ссылка. Дальше буквы на месте точек — что отличалось: s размер, t время, p права, o владелец, g группа. +++++++++ — новый файл.
Коды возврата
| Код | Значение |
|---|
0 | успех |
23 | часть файлов не передана (нет доступа, нет источника) |
24 | часть файлов исчезла во время копирования |
25 | сработал --max-delete |
12, 255 | обрыв связи / ошибка SSH |
Примеры
# зеркало каталога: содержимое /srv/app в /srv/backup/app
rsync -a /srv/app/ /srv/backup/app/
# сначала посмотреть, что изменится и что удалится
rsync -avn --delete /srv/app/ /srv/backup/app/
# точное зеркало с удалением лишнего
rsync -a --delete /srv/app/ /srv/backup/app/
# без логов, зависимостей и .git
rsync -a --exclude='*.log' --exclude='node_modules/' --exclude='.git/' ~/project/ /srv/app/
# только .conf, с сохранением структуры каталогов и без пустых каталогов
rsync -am --include='*/' --include='*.conf' --exclude='*' /etc/ /srv/backup/etc-conf/
# выложить на сервер по SSH со сжатием и прогрессом
rsync -azh --progress ~/project/ deploy@example.com:/srv/app/
# нестандартный порт SSH и свой ключ
rsync -az -e 'ssh -p 2222 -i ~/.ssh/deploy' ~/project/ deploy@example.com:/srv/app/
# забрать логи с сервера к себе
rsync -az deploy@example.com:/var/log/nginx/ ./nginx-logs/
# выложить с правильными владельцем и правами
rsync -a --chown=www-data:www-data --chmod=D755,F644 ./public/ /srv/app/public/
# большой файл по нестабильной сети — с докачкой
rsync -P backup.tar.gz deploy@example.com:/srv/backup/
# ежедневный снимок: неизменённые файлы — жёсткие ссылки на вчерашние
rsync -a --delete --link-dest=/srv/snap/yesterday /srv/app/ /srv/snap/today/
# показать по каждому файлу, что именно отличается
rsync -ai /srv/app/ /srv/backup/app/
Подводные камни
- Слеш в конце источника меняет результат.
src и src/ — разные команды: без слеша внутри приёмника появится лишний уровень src/. Особенно опасно вместе с --delete.
--delete удаляет без вопросов. Если перепутать источник с приёмником или указать не тот каталог, данные пропадут. Всегда сначала запускай с -n, а в скриптах добавляй --max-delete.
- Исключённые файлы
--delete не трогает. Файл, подпавший под --exclude, останется в приёмнике. Чтобы удалить и его, нужен --delete-excluded.
- Шаблоны исключений.
--exclude=sub исключит sub на любом уровне, --exclude=/sub — только в корне источника. Слеш в конце (node_modules/) — только каталоги.
- Порядок
--include и --exclude важен: срабатывает первое подходящее правило. Чтобы взять только *.conf, нужны --include='*/' (иначе rsync не зайдёт в подкаталоги), потом --include='*.conf', и в конце --exclude='*'.
- Приёмник создаётся только на один уровень.
rsync -a src/ /нет/такого/пути/ упадёт с «mkdir failed», если нет родительских каталогов. Создай их заранее или добавь --mkpath.
- Без приёмника
rsync ничего не копирует, а печатает список файлов, как ls -l. Забытый аргумент легко не заметить.
- Одинаковый размер и время — «файл не изменился». Файл с другим содержимым, но тем же размером и временем изменения,
rsync пропустит. Для проверки по содержимому нужен -c.
- Владельцы сохраняются только у root. Обычный пользователь получит все файлы на себя.
-a не сохраняет жёсткие ссылки — для них нужен -H.
- На удалённой машине тоже нужен
rsync. Без него соединение по SSH оборвётся с ошибкой «connection unexpectedly closed».
См. также
ssh · tar · cp · find · cron · chown · ln