Rsync — synchronizacja katalogów przez SSH, kopia zapasowa i mirror
rsync to narzędzie linuksowe do przenoszenia katalogów między maszynami bez wysyłania od nowa tego, co już jest po drugiej stronie. Algorytm transferu różnicowego wysyła tylko bajty, które zmieniły się od ostatniego uruchomienia — dlatego dzienna kopia 200 GB kończy się w dwie minuty zamiast w dwie godziny. Polecenie rsync można wpisać ręcznie, ale gdy w grę wchodzi niestandardowy port SSH, lista wykluczeń i decyzja, czy robisz przyrostową kopię czy pełny mirror, generator zaczyna się opłacać. Ten artykuł pokazuje konstrukcję polecenia rsync, działający workflow przez SSH, różnicę między kopią przyrostową a --delete, i sześć błędów, które po cichu psują backupy zanim ktoś to zauważy.
Generator Rsync — co robi i komu się przyda
Generator Rsync buduje pełne polecenie rsync z krótkiego formularza. Wpisujesz adres serwera, ścieżki źródłową i docelową, port SSH, nazwę użytkownika, wybierasz czy lokalna maszyna jest źródłem czy celem — generator wypluwa gotowe do wklejenia polecenie i mały skrypt powłoki (rsync-source.sh lub rsync-destination.sh), który możesz wrzucić do katalogu z backupami.
Narzędzie celuje w trzy konkretne profile. Pierwszy: deweloper, który ściąga produkcyjną stronę WWW na laptopa do lokalnego debugowania — to dokładnie scenariusz ze zrzutu ekranu w nagłówku, gdzie /var/www/pyrek.com.pl/ ze zdalnego VPS-a leci do ~/Projects/www.pyrek.com.pl/ na Macu. Drugi: administrator, który chce codzienny backup /etc, /var/www albo katalogu z dumpami baz wypychany na zewnętrzny serwer przez SSH. Trzeci: każdy, kto wpisał rsync -avz -e "ssh -p ..." wystarczająco wiele razy, żeby wiedzieć, że zawsze zapomni o ukośniku na końcu źródłowej ścieżki.
Generator oszczędza pamięć mięśniową i grzebanie po stronie man. Składnia -e "ssh -p PORT" jest upierdliwa — cudzysłowy mają znaczenie, kolejność ma znaczenie, a źle postawiony dwukropek zamienia zdalną synchronizację na lokalne kopiowanie pliku z dwukropkiem w nazwie.
Praktyka — rsync przez SSH krok po kroku
Cel tej sekcji to działające polecenie, które zsynchronizuje katalog między lokalną maszyną a zdalnym serwerem, pójdzie po SSH na niestandardowym porcie i pokaże postęp w trakcie pracy. Zaczynamy od jednorazowego pobrania, potem omówimy każdą flagę, na końcu zamienimy to w skrypt do cron.
Krok 1 — sprawdź, czy rsync jest po obu stronach
rsync jest domyślnie dostępny w większości dystrybucji Linuksa, ale zdalny serwer też go potrzebuje — nie tylko lokalna maszyna. Zdalny binarny rsync odpowiada lokalnemu klientowi po sieciowym protokole; bez niego dostaniesz rsync: command not found po SSH i transfer w ogóle nie ruszy.
# Sprawdzenie wersji lokalnie
rsync --version
# Sprawdzenie wersji na zdalnym serwerze
ssh -p 5840 root@198.51.100.42 'rsync --version'
Na Debianie i Ubuntu instalacja przez apt install rsync, na RHEL-u i Rocky przez dnf install rsync. macOS dostarcza domyślnie stary rsync 2.6.9 — do poważnej pracy zainstaluj świeżą wersję przez Homebrew (brew install rsync), która daje 3.x z aktualnym algorytmem różnicowym i działającym --info=progress2.
Krok 2 — uwierzytelnianie kluczem SSH
rsync może działać z hasłem, ale wtedy wpisujesz je przy każdym uruchomieniu, a zadania cron z hasłem albo nie działają wcale, albo cicho zawisają. Generujesz klucz, wrzucasz publiczną połówkę do authorized_keys na zdalnym serwerze i temat zamknięty:
# Generowanie klucza Ed25519 (szybszy, krótszy, nowoczesny domyślny)
ssh-keygen -t ed25519 -C "klucz do backupow rsync" -f ~/.ssh/rsync_key
# Skopiowanie klucza publicznego na zdalny serwer
ssh-copy-id -i ~/.ssh/rsync_key.pub -p 5840 root@198.51.100.42
Jeśli ssh-copy-id nie jest dostępne (niektóre instalacje macOS), dopisz ~/.ssh/rsync_key.pub do ~/.ssh/authorized_keys na zdalnym hoście ręcznie i upewnij się, że uprawnienia to 700 na ~/.ssh i 600 na authorized_keys. SSH odrzuca klucze z uprawnieniami pozwalającymi czytać je grupie albo światu.
Krok 3 — podstawowa konstrukcja polecenia
Tak wygląda kanoniczne polecenie rsync przez SSH — to dokładnie to, co generator produkuje dla zrzutu ekranu na początku artykułu:
rsync -av --progress -e "ssh -p 5840" \
root@198.51.100.42:/var/www/example.com/ \
/Users/admin/Projekty/example.com/
Czytaj od lewej do prawej. Flagi -a i -v włączają tryb archiwizacji i tryb gadatliwy. --progress pokazuje pasek postępu per plik. -e "ssh -p 5840" mówi rsync-owi, jakiego transportu użyć i nadpisuje domyślny port SSH. Pierwsza ścieżka to źródło — uwaga na dwukropek między hostem a ścieżką, to on robi z lokalizacji „zdalną". Druga ścieżka to lokalny cel.
Ukośnik na końcu ścieżki źródłowej znaczy więcej, niż ludzie myślą. /var/www/example.com/ (z ukośnikiem) znaczy „skopiuj zawartość tego katalogu do celu". /var/www/example.com (bez ukośnika) znaczy „skopiuj sam katalog do celu", co produkuje /Users/admin/Projekty/example.com/example.com/. Raz, gdy zagnieździsz katalog w sobie samym przez przypadek, już nigdy o tej zasadzie nie zapomnisz.
Krok 4 — co naprawdę robią flagi
Stos flag -av i znajomi wygląda jak jedna opcja, ale każda litera robi coś konkretnego. Warto wiedzieć co:
-a(archive) — łączy-rlptgoD. Rekurencyjnie, zachowuje dowiązania symboliczne, uprawnienia, czasy modyfikacji, grupę i właściciela, plus pliki specjalne urządzeń. Tej flagi chcesz do backupów i mirrorów. Nie zachowuje twardych dowiązań (do tego-H) ani rozszerzonych atrybutów (-X/-A).-v(verbose) — wypisuje nazwy plików w trakcie przetwarzania. Przy bardzo dużych transferach albo zrezygnuj, albo połącz z--info=progress2dla pojedynczego paska postępu zamiast linijki na każdy plik.-z(compress) — kompresuje dane w locie. Przydatne na wolnym łączu albo dla dużej ilości tekstu. Pomijaj przy już skompresowanych danych (filmy, JPEG-i, archiwa.tar.gz); CPU kosztuje więcej niż zaoszczędzisz na pasmie.--progress— postęp per plik. Nowszyrsync(3.1+) ma też--info=progress2, czyli zbiorczy pasek postępu dla całego transferu — to chcesz do backupów.-P— skrót na--progress --partial. Część--partialzostawia połówkowo przesłane pliki na dysku przy zerwanym połączeniu, więc kolejne uruchomienie wznawia transfer od miejsca, w którym poprzedni padł.--delete— usuwa z celu pliki, których nie ma już w źródle. To zamienia kopię przyrostową w prawdziwy mirror. Niebezpieczna flaga: literówka w ścieżce źródłowej potrafi wyczyścić cel. Pierwsze uruchomienie zawsze z--dry-run.-n/--dry-run— symulacja transferu bez pisania niczego. Obowiązkowo przed--deletena danych, na których ci zależy.-e— wskazuje powłokę zdalną. Używamy do przekazania opcji SSH jak niestandardowego portu (-e "ssh -p 5840") albo konkretnego klucza (-e "ssh -i ~/.ssh/rsync_key").
Krok 5 — kopia przyrostowa kontra pełny mirror
Checkbox „Kopia przyrostowa" w generatorze kontroluje jedno krytyczne zachowanie: czy rsync ma usuwać z celu pliki, których nie ma już w źródle.
# Kopia przyrostowa — dodaje i aktualizuje, nigdy nie usuwa
rsync -av --progress -e "ssh -p 5840" \
root@198.51.100.42:/var/www/example.com/ \
/Users/admin/Projekty/example.com/
# Pełny mirror — cel ma być identyczny ze źródłem, łącznie z usunięciami
rsync -av --delete --progress -e "ssh -p 5840" \
root@198.51.100.42:/var/www/example.com/ \
/Users/admin/Projekty/example.com/
Do roboczej kopii strony WWW na lokalnym dysku przyrostowa jest sensowna — nie chcesz tracić lokalnych poprawek tylko dlatego, że na zdalnym ktoś usunął plik. Do offsite-owej kopii zapasowej, która ma odwzorowywać stan produkcji jeden do jednego, potrzebujesz --delete. Bądź świadomy, którą wersję uruchamiasz.
Krok 6 — wykluczanie plików, których nie chcesz kopiować
Praktycznie każda realna synchronizacja potrzebuje listy wykluczeń. Cache, wewnętrzne katalogi systemu kontroli wersji, logi i node_modules nie powinny zżerać pasma.
rsync -av --progress \
--exclude='.git/' \
--exclude='node_modules/' \
--exclude='*.log' \
--exclude='cache/' \
-e "ssh -p 5840" \
root@198.51.100.42:/var/www/example.com/ \
/Users/admin/Projekty/example.com/
Przy długich listach lepiej wskazać plik przez --exclude-from=excludes.txt — jedna reguła na linię, komentarze przez #. Tak robi się to w produkcyjnych skryptach backupowych i tak łatwiej trzymać listę pod kontrolą wersji niż ścianę flag --exclude.
Krok 7 — skrypt do crona
Minimalny, ale gotowy do produkcji skrypt backupowy. Pełen zestaw opcji znajdziesz w oficjalnej dokumentacji rsync:
#!/bin/bash
# /usr/local/bin/backup-www.sh
set -euo pipefail
SRC="root@198.51.100.42:/var/www/"
DST="/srv/backups/www/"
LOG="/var/log/rsync-www.log"
rsync -az --delete --partial \
-e "ssh -p 5840 -i /root/.ssh/rsync_key" \
--exclude-from=/etc/rsync/excludes.txt \
"$SRC" "$DST" >> "$LOG" 2>&1
if [ $? -ne 0 ]; then
echo "rsync padł $(date)" | mail -s "Backup nie wyszedł" admin@example.com
fi
Wpis do cron przez crontab -e:
# Codziennie o 02:00
0 2 * * * /usr/local/bin/backup-www.sh
Ten wzorzec — pojedynczy skrypt, klucz SSH, plik z wykluczeniami, log, powiadomienie o porażce — to wystarczająca infrastruktura, żeby działać latami. W parze z generatorem Let's Encrypt, jeśli musisz backupować też /etc/letsencrypt/ — a musisz.
Częste błędy i pułapki
Brak ukośnika na końcu źródła
rsync -av /var/www example.com:/backup/ kopiuje katalog /var/www do /backup/, co produkuje /backup/www/. rsync -av /var/www/ example.com:/backup/ kopiuje zawartość /var/www do /backup/. To nie jest to samo, a różnica wychodzi w postaci zagnieżdżonych katalogów albo, gorzej, plików w złym miejscu. Przemyśl, co masz na myśli, i sprawdź ukośnik.
--delete bez --dry-run na pierwszym uruchomieniu
--delete usuwa z celu wszystko, czego nie ma w źródle. Jeśli pomylisz źródło z celem albo wskażesz złą ścieżkę, zsynchronizujesz pusty katalog na dane. Zawsze najpierw -n i przeczytaj listę plików. Jeśli cokolwiek na liście „deleting" cię zaskakuje — nie odpalaj prawdziwej komendy.
rsync: command not found po stronie zdalnej
Zdalny serwer też potrzebuje zainstalowanego rsync — lokalny klient woła zdalnego klienta po SSH i komunikują się protokołem. Błąd pojawia się jako rsync: connection unexpectedly closed albo dosłownie rsync: command not found w strumieniu SSH. Naprawa: apt install rsync albo dnf install rsync na zdalnym.
Permission denied (publickey) po skonfigurowaniu kluczy
Najczęstsza przyczyna: bity uprawnień na zdalnym ~/.ssh albo authorized_keys. SSH odrzuca klucze, które uważa za zbyt otwarte. Na zdalnym serwerze: chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys. Druga w kolejności przyczyna: klucz publiczny został wklejony z łamaniem linii albo dodatkowymi spacjami. Otwórz authorized_keys i sprawdź, czy klucz jest w pojedynczej linii.
Pliki przesyłają się od nowa przy każdym uruchomieniu
Zwykle problem z czasem modyfikacji. Systemy plików FAT (pendrive'y), niektóre montowania NFS i pewne sterowniki wolumenów Dockera nie zachowują czasu modyfikacji dokładnie. rsync widzi inny timestamp i przesyła plik ponownie. Dodaj tymczasowo --checksum, żeby potwierdzić, że pliki są bajt-w-bajt identyczne, a potem albo napraw system plików po stronie celu, albo pogódź się z --checksum na stałe (wolniej, ale dokładnie).
-z spowalnia transfer w szybkiej sieci
Kompresja -z pomaga na wolnych łączach i przy danych tekstowych. Na 1 Gbps LAN-ie przy już skompresowanych plikach (filmy, JPEG-i, archiwa) koszt CPU na kompresję przekracza zaoszczędzone pasmo. Wywal -z i zobacz, jak rośnie przepustowość.
Połączenie SSH zrywa się i transfer zaczyna od zera
Bez --partial rsync przy zerwanym połączeniu kasuje niedokończone pliki, a kolejne uruchomienie zaczyna każdy plik od zera. Używaj -P (czyli --partial --progress) przy każdym transferze, gdzie łącze może być chwiejne albo pliki są duże.
FAQ — najczęściej zadawane pytania
Jak uruchomić rsync na niestandardowym porcie SSH?
Użyj flagi -e, żeby przekazać port do SSH: rsync -av -e "ssh -p 5840" zrodlo/ user@host:cel/. Cudzysłowy wokół "ssh -p 5840" mają znaczenie — bez nich powłoka rozdziela argument i rsync źle interpretuje komendę. Generator Rsync na vps.pyrek.com.pl produkuje dokładnie tę składnię automatycznie, gdy wpiszesz niestandardowy port.
Czym różni się rsync od scp?
scp kopiuje pliki za każdym razem od zera, bez świadomości tego, co już jest po drugiej stronie. rsync porównuje źródło z celem przed transferem i wysyła tylko bajty, które się różnią. Do jednorazowego kopiowania pojedynczego pliku oba narzędzia są równoważne; do powtarzanej synchronizacji dużych katalogów rsync jest dramatycznie szybszy. Nowoczesny OpenSSH zresztą wycofał stary protokół scp na rzecz SFTP — kolejny powód, żeby domyślnie sięgać po rsync.
Czy mogę zrobić backup zdalnego serwera na lokalną maszynę?
Tak — to wzorzec „pull" i często jest bezpieczniejszy niż „push". Źródło ustawiasz po stronie zdalnej (user@host:/sciezka/), cel lokalnie. Lokalna maszyna inicjuje połączenie, trzyma klucz SSH i pisze na własny dysk — zdalny serwer nigdy nie dostaje uprawnień do pisania w drugą stronę. To dokładnie to, co widać na zrzucie ekranu nad artykułem: laptop dewelopera ściąga /var/www/www.pyrek.com.pl/ z VPS-a do ~/Projects/.
Czy rsync wznawia przerwane transfery?
Tylko jeśli mu każesz. Domyślnie rsync kasuje niedokończone pliki przy zerwaniu połączenia. Dodaj --partial (albo -P, które łączy --partial i --progress), żeby zostawiał na dysku częściowe pliki — kolejne uruchomienie podejmie pracę tam, gdzie poprzednie skończyło. Przy dużych plikach na chwiejnym łączu to obowiązkowe.
Jak wykluczyć .git, node_modules i podobne katalogi?
Z linii poleceń: --exclude='.git/' i --exclude='node_modules/', albo — przy dłuższych listach — --exclude-from=sciezka/do/excludes.txt z jedną regułą na linię. Wzorce dopasowują się od korzenia drzewa źródłowego; prowadzący / kotwiczy regułę, kończący / ogranicza dopasowanie do katalogów. Przed produkcyjnym uruchomieniem przetestuj reguły przez --dry-run -v.
Czy rsync zachowa uprawnienia, właściciela i czas modyfikacji plików?
Flaga -a (archive) zachowuje uprawnienia (-p), czasy modyfikacji (-t), grupę (-g), właściciela (-o, wymaga roota albo zgodnego UID) i wchodzi rekurencyjnie w katalogi (-r). Nie zachowuje twardych dowiązań (dodaj -H), list ACL (-A) ani rozszerzonych atrybutów (-X). Do pełnego mirrora na poziomie systemu plików: -aHAX.
Czy mogę uruchamiać rsync bez konta root na zdalnym?
Tak i tam, gdzie się da, powinieneś. Załóż na zdalnym dedykowane konto bez uprawnień (backup-user albo podobne), daj mu prawa odczytu na katalogi, które chcesz backupować, a klucz SSH zamknij w authorized_keys przez command="rsync --server ...". Składnię ograniczeń opisuje dokumentacja OpenSSH dotycząca authorized_keys.
Jak włączyć pojedynczy pasek postępu zamiast jednej linii na plik?
Użyj --info=progress2 (rsync 3.1.0 i nowszy). Zastępuje wypisywanie nazw plików zbiorczym paskiem, który pokazuje łączną liczbę przesłanych bajtów, procent ukończenia i ETA. Dołóż --no-inc-recursive, jeśli chcesz, żeby procent był poprawny od początku, a nie rósł w miarę odkrywania kolejnych plików przez rsync.
Następne kroki
Pełną komendę rsync — z twoim adresem serwera, ścieżkami, portem i właściwym wyborem --delete — wygenerujesz w generatorze Rsync. Szybciej niż wpisywanie bloku -e "ssh -p ..." z głowy i trudniej pomylić ukośniki na końcu ścieżek.
Powiązane tematy, które rozszerzają realny workflow backupowy:
- Generator VirtualHost Apache2 — przy odtwarzaniu kopii na świeży serwer pliki vhost muszą się zgadzać.
- Generator serwera DNS Bind 9 — konfiguracja DNS to kolejny naturalny cel offsite-owego rsync.
Wolisz wideo? Zajrzyj na mój kanał YouTube — praktyczna administracja Linuksa, Proxmox i self-hosting.