Jak tworzyć kopie zapasowe cronem

dowiedz się

Automatyczna kopia danych oszczędza czas, ogranicza ryzyko pomyłek i zwiększa odporność systemu na awarie. Najprostszym sposobem regularnego uruchamiania zadań w systemach Linux/UNIX jest zadaniownik cron. Poniżej znajdziesz kompletną instrukcję: od planowania, przez tworzenie skryptu i konfigurację, aż po rotację i weryfikację integralności. Zobaczysz praktyczne przykłady i dobre praktyki, aby Twoje backupy były przewidywalne, szybkie i możliwe do odtworzenia w kryzysie.

Plan i przygotowanie środowiska

Zakres: co, jak często i po co kopiujesz

Najpierw zdecyduj, które zasoby obejmiesz kopią. Typowy zestaw to katalogi z konfiguracją (np. /etc), dane użytkowników (np. /home, /var/www), artefakty aplikacji i bazy danych. Dla każdego zasobu określ dwa parametry: jak często może być tworzona kopia (RPO) oraz jak szybko musisz dane odtworzyć (RTO). Wpływa to na strukturę, objętość i koszt kopii.

Przykładowy podział częstotliwości:

  • Co godzinę: najmniejsze, krytyczne przyrosty (np. dzienniki aplikacji, niewielkie zbiory bieżących plików).
  • Codziennie w nocy: pełne kopie ważnych katalogów i zrzuty baz.
  • Co tydzień: pełne kopie z szerszą retencją.
  • Co miesiąc: migawki archiwalne, trzymane dłużej (np. 6–12 miesięcy).

Zadbaj, by kopie były spójne aplikacyjnie. Dla baz danych używaj dedykowanych narzędzi do zrzutów, a dla maszyn wirtualnych – migawki hypervisora.

Miejsce docelowe i zasada 3-2-1

Wybierz przestrzeń na kopie: lokalny dysk, udział sieciowy, obiektowy storage w chmurze lub nośnik offline. Kieruj się zasadą 3-2-1: trzy kopie danych, na dwóch różnych nośnikach, jedna offsite. Lokalne kopie przyspieszają odtwarzanie, kopie zdalne chronią przed pożarem, kradzieżą lub ransomware.

Ustal strukturę katalogów docelowych. Polecany schemat: /var/backups/NAZWA_HOStA/ROK-MIESIĄC-DZIEŃ/sekcja. Dzięki temu łatwo znaleźć najnowszy punkt przywracania oraz rozdzielić typy danych.

Narzędzia, z których skorzystasz

Do przenoszenia i porównywania plików świetnie nadaje się rsync. Wykonuje kopie przyrostowe, potrafi usuwać elementy usunięte ze źródła i oszczędza transfer. Spakowanie wielu plików w jeden archiwum ułatwia tar, a kompresję warto dobrać do rodzaju danych: gzip (szybko), xz (mocno), zstd (dobry kompromis). Dla baz MySQL/MariaDB stosuj mysqldump lub narzędzia percona/xtrabackup; dla PostgreSQL – pg_dump/pg_dumpall; dla SQLite – walutowa kopia pliku po checkpoint.

Do ochrony poufności użyj szyfrowania na poziomie plików (np. gpg, openssl) lub repozytoriów kopii. Gdy kopiujesz do chmury, rclone obsługuje S3, Azure, GDrive i zapewnia wbudowane szyfrowanie oraz walidację.

Użytkownik i uprawnienia

Kopie wykonuj z dedykowanego użytkownika (np. backup), posiadającego minimalne niezbędne uprawnienia do odczytu danych. Jeżeli musisz odczytać katalogi systemowe, rozważ sudo ograniczone tylko do wymaganych poleceń. Katalog docelowy/klucze ustaw z restrykcyjnymi uprawnieniami (np. 700 dla katalogów, 600 dla plików kluczy i haseł).

Wymagania niefunkcjonalne: czas, I/O, okno serwisowe

Wielkość danych oraz kompresja wpływają na czas trwania kopii. Zadbaj o okno, w którym obciążenie I/O nie zakłóci systemu produkcyjnego. Pomoże nice/ionice, limit przepustowości rsync (–bwlimit), a także podział kopii na mniejsze porcje i równoległość tam, gdzie to bezpieczne.

Skrypt tworzący kopię zapasową

Struktura i zmienne środowiskowe

Dobrą praktyką jest jeden główny skrypt uruchamiany przez cron, który:

  • Inicjuje zmienne (datę, host, katalog docelowy).
  • Tworzy strukturę katalogów.
  • Wykonuje poszczególne etapy kopii (pliki, bazy, dodatkowe dane).
  • Opcjonalnie szyfruje, tworzy sumy kontrolne, pakuje raport.
  • Zwraca kod powodzenia lub porażki i zapisuje log.

Przykładowy szkielet (zapisz jako /usr/local/bin/backup.sh i nadaj uprawnienia 750):

#!/bin/bash

set -euo pipefail

DATE=$(date +%F)

HOST=$(hostname -s)

BASE=”/var/backups”

DEST=”$BASE/$HOST/$DATE”

LOG=”$DEST/logs/backup.log”

mkdir -p „$DEST/files” „$DEST/db” „$DEST/logs”

exec > >(tee -a „$LOG”) 2>&1

echo „Start: $(date -Is)”

Kopia plików z rsync

Jeżeli chcesz wiernie odtworzyć strukturę plików, rsync jest narzędziem pierwszego wyboru. Główne opcje: -a (archiwizacja), –delete (usuwa elementy usunięte u źródła), –numeric-ids (spójność UID/GID), –link-dest (kopia przyrostowa z twardymi linkami), –checksum (gdy chcesz porównać sumy zamiast czasów modyfikacji). Minimalny przykład:

rsync -a –delete /etc/ „$DEST/files/etc/”

Wiele katalogów dodasz w kolejnych liniach:

rsync -a –delete /home/ „$DEST/files/home/”

rsync -a –delete /var/www/ „$DEST/files/www/”

Aby ograniczyć transfer lub wpływ na I/O:

  • rsync -a –bwlimit=10m … (limit przepustowości)
  • nice -n 15 rsync … oraz ionice -c2 -n7 rsync … (priorytety CPU i I/O)

Archiwizacja i kompresja za pomocą tar

Gdy masz tysiące drobnych plików lub chcesz łatwo przenosić dane jako jeden artefakt, użyj tar:

tar -czf „$DEST/files/home.tar.gz” /home

Inne warianty: tar -I 'zstd -19′ -cf „$DEST/files/www.tar.zst” /var/www

Tar oferuje też kopię przyrostową (–listed-incremental). Przygotuj plik stanu i wykonuj pełną kopię cyklicznie (np. raz w tygodniu), a w pozostałe dni przyrosty. Pamiętaj, że odtwarzanie przyrostów wymaga kolejności: pełna, a potem kolejne przyrosty.

Zrzuty baz danych

Bazy wymagają spójności logicznej. Dla MySQL/MariaDB:

mysqldump –single-transaction –routines –triggers –events –all-databases | gzip > „$DEST/db/mysql.sql.gz”

Parametr –single-transaction ogranicza blokady w silniku InnoDB. Dla dużych instancji rozważ narzędzia wykonujące kopie na poziomie fizycznym, ale tu pozostajemy przy zrzutach logicznych.

Dla PostgreSQL:

pg_dumpall -U postgres | gzip > „$DEST/db/postgres.sql.gz”

lub per-baza: pg_dump -U postgres -d NAZWA_BAZY -Fc -f „$DEST/db/NAZWA_BAZY.dump”

Pamiętaj o bezpiecznym uwierzytelnianiu (np. ~/.pgpass z uprawnieniami 600) i ograniczeniu dostępu do plików zrzutów.

Szyfrowanie i sumy kontrolne

Jeżeli kopie trafiają poza zaufaną infrastrukturę lub zawierają dane osobowe, szyfruj artefakty. Prosty wariant z gpg i kluczem publicznym odbiorcy:

gpg –recipient backup@firma.pl –output „$DEST/files/home.tar.gz.gpg” –encrypt „$DEST/files/home.tar.gz”

Kiedy używasz hasła symetrycznego, przechowuj je poza skryptem (np. w pliku konfiguracyjnym czy managerze sekretów) i ogranicz uprawnienia.

W celu wykrycia uszkodzeń zapisz sumy kontrolne:

(cd „$DEST” && find . -type f ! -name „checksums.sha256” -exec sha256sum {} +) > „$DEST/checksums.sha256”

Weryfikacja w późniejszym czasie:

(cd „$DEST” && sha256sum -c checksums.sha256)

Logowanie, kody zakończenia i pułapki

Skrypt powinien wyjść z kodem != 0 po błędzie. set -euo pipefail i sprawdzanie statusu ostatniego polecenia zredukuje „ciche” awarie. Zapisuj czas startu i końca, rozmiary plików oraz wolne miejsce w systemie plików (df -h). W razie braku miejsca przerwij pracę i zgłoś błąd, aby nie produkować niekompletnych kopii.

Minimalny epilog skryptu:

echo „Koniec: $(date -Is)”

exit 0

Konfiguracja harmonogramu w cron

Składnia i środowisko

Wpis w cronie ma pięć pól czasu i polecenie: min godzina dzień_miesiąca miesiąc dzień_tygodnia polecenie. Aby uniknąć problemów z ścieżkami, ustaw PATH na początku pliku crontab oraz określ SHELL, MAILTO i umask. Przykład nagłówka:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

SHELL=/bin/bash

MAILTO=admin@firma.pl

UMASK=077

Takie ustawienia ograniczają ryzyko uruchomienia niechcianych poleceń i pozwalają wysyłać raporty mailem przy błędach.

Edycja crontab i poziomy

Crontab użytkownika edytujesz poleceniem: crontab -e. Zadania w /etc/crontab oraz /etc/cron.d mają inny format (z dodatkową kolumną „użytkownik”). Dla kopii systemowych preferuj konto „backup” i plik w /etc/cron.d/backup, aby separować konfigurację.

Przykład (plik /etc/cron.d/backup):

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

SHELL=/bin/bash

MAILTO=admin@firma.pl

UMASK=077

0 2 * * * backup /usr/local/bin/backup.sh

Wpis uruchomi kopię codziennie o 02:00 jako użytkownik backup.

Przykładowe harmonogramy

Pełna kopia plików codziennie o 02:00, zrzuty baz o 02:30, rotacja o 03:00:

0 2 * * * backup /usr/local/bin/backup.sh –files

30 2 * * * backup /usr/local/bin/backup.sh –db

0 3 * * * backup /usr/local/bin/backup-rotate.sh

Szybki przyrost co godzinę dla wybranego katalogu:

15 * * * * backup /usr/local/bin/backup.sh –fast-incremental /var/www

Wykorzystanie skrótów: @daily, @weekly, @monthly, @reboot:

@weekly backup /usr/local/bin/backup-verify.sh

Zmienność i kolizje zadań

Aby uniknąć nakładania się zadań, używaj lockfile (np. flock) lub katalogów blokujących. Przykład:

/usr/bin/flock -n /var/lock/backup.lock /usr/local/bin/backup.sh

Jeżeli serwer może być w trybie uśpienia, zadbaj o wybudzenie lub użyj anacron, który wykona zadania pominięte, gdy system był wyłączony.

Alternatywy i integracje

Jeśli pracujesz na dystrybucjach z systemd, rozważ systemd timers jako alternatywę dla crona w przypadku zadań wymagających zaawansowanych zależności, limitów i logowania do journal. Mechanizm jest komplementarny — możesz używać timerów do zadań krytycznych, a crona do reszty.

Retencja, weryfikacja i bezpieczeństwo

Polityka retencji i rotacja

Retencja definiuje, jak długo trzymasz poszczególne typy kopii. Przykład: przyrosty godzinne — 24h, kopie dzienne — 14 dni, tygodniowe — 8 tygodni, miesięczne — 12 miesięcy. Uporządkuj katalogi według dat i stosuj proste reguły usuwania.

Przykładowy skrypt rotacji (7 dni dla dziennych):

find /var/backups/$(hostname -s) -maxdepth 1 -type d -mtime +7 -name „20*” -exec rm -rf {} +

Jeżeli tworzysz archiwa tar, możesz rotować po rozmiarze lub liczbie wersji (np. zostaw 7 najnowszych). W przypadku rclone do S3 użyj lifecycle rules po stronie bucketu.

Testy odtwarzania i przywracanie

Kopia nie istnieje, dopóki nie sprawdzisz odtwarzania. Wydziel środowisko testowe i okresowo odtwórz:

  • Pliki: przywróć do katalogu tymczasowego i porównaj sumy kontrolne.
  • Bazy: odtwórz z dumpa do testowej instancji i wykonaj zapytania sanity-check.
  • Usługi: uruchom aplikację na danych z kopii i sprawdź kluczowe funkcje.

Przykłady:

tar -xzf /var/backups/HOST/2024-12-01/files/home.tar.gz -C /tmp/restore

mysql -u root -p < /var/backups/HOST/2024-12-01/db/mysql.sql.gz (z wykorzystaniem zcat)

Dla rsync odwrotne kopiowanie:

rsync -a /var/backups/HOST/2024-12-01/files/www/ /tmp/restore/www/

Warto też okresowo sprawdzić sumy:

(cd /var/backups/HOST/2024-12-01 && sha256sum -c checksums.sha256)

Monitoring, alerty i logi

Raporty z kopii wysyłaj e-mailem lub do systemu obserwowalności (Prometheus, ELK, Graylog). W cronie ustaw MAILTO, a w skrypcie loguj kluczowe metryki: czas trwania, rozmiar (du -sh), wolne miejsce (df -h), liczba błędów. Przy problemach z pocztą skonfiguruj alternatywę (np. webhook do Slack/Teams).

Logi obracaj przez logrotate, aby nie rosły bez końca. Wzorzec: /var/log/backup/*.log z rotacją dzienną i przechowaniem np. 14 plików.

Ochrona kluczy i uprawnień

Najczęstszy błąd to pozostawienie kluczy i haseł zbyt szeroko dostępnych. Katalog /var/backups i pliki zrzutów powinny należeć do użytkownika backup i mieć minimalne uprawnienia. Klucze GPG trzymaj w katalogu domowym backup (np. /home/backup/.gnupg), z uprawnieniami 700. Jeżeli używasz rclone z szyfrowaniem, ogranicz dostęp do pliku konfiguracyjnego (~/.config/rclone/rclone.conf) i nie zapisuj haseł wprost — użyj menedżera sekretów lub zmiennych środowiskowych.

Optymalizacja wydajności

Przy dużych zbiorach danych rozważ przyrostowe kopie z rsync i linkami twardymi (–link-dest), które pozwalają tworzyć „pełne” migawki przy oszczędnym wykorzystaniu miejsca. Alternatywnie użyj narzędzi deduplikujących (borg, restic), które lokalnie i zdalnie oszczędzają przestrzeń. Kompresję dobieraj per typ danych: dla już skompresowanych (jpg, mp4) ją pomijaj, a dla tekstu stosuj zstd/gzip.

W przypadku baz danych duże przyrosty można ograniczyć replikacją i wykonywaniem kopii z repliki, aby nie dociążać produkcyjnego mastera. Ustal okna backupowe tak, aby kolidowały jak najmniej z zadaniami utrzymaniowymi (vacuum, analyze, sprzątanie logów).

Przesył i kopie offsite

Aby utrzymać trzecią kopię offsite, użyj rclone do S3 lub innego backendu:

rclone copy –checksum –transfers=8 –checkers=16 –bwlimit=20M „$DEST” s3:moj-bucket/kopie/$HOST/$DATE

Z włączonym versioningiem i object lock (WORM) w bucketach ograniczysz ryzyko skasowania kopii przez błędny skrypt lub złośliwe oprogramowanie. Wrażliwe katalogi wysyłaj po uprzednim zaszyfrowaniu, albo włącz warstwę szyfrowania rclone (remote crypt).

Najczęstsze problemy i ich diagnoza

Środowisko crona różni się od interaktywnej powłoki: brak tego samego PATH, brak zmiennych, inny katalog roboczy. Dlatego używaj ścieżek bezwzględnych, ustaw zmienne na początku, a polecenia testuj z symulacją środowiska (env -i SHELL=/bin/bash PATH=… /usr/local/bin/backup.sh). Sprawdzaj systemowy syslog/cron log (np. /var/log/syslog, /var/log/cron) w przypadku „milczących” porażek.

Gdy skrypt działa z palca, ale nie z crona, najczęściej winny jest brak PATH, brak uprawnień do katalogu docelowego lub różnice w locale. Dodanie LANG=C i LC_ALL=C na początku może zapobiec błędom z nie-ASCII w nazwach plików.

Dodatkowe usprawnienia

Warto wdrożyć weryfikację wolnego miejsca i bezpieczne przerwanie, jeżeli zostało go mniej niż określony próg. Dodaj również raport z listą największych plików (du -x /… | sort -rh | head -n 20), aby identyfikować niespodziewane wzrosty wolumenu. Jeśli kopiujesz wielkie repozytoria git lub cache aplikacji, rozważ ich wykluczenie (rsync –exclude, tar –exclude) i odtworzenie z definicji zamiast przechowywania.

Przykładowy kompletny przebieg

1) O 01:55 skrypt sprawdza wolne miejsce i tworzy lock.

2) O 02:00 rozpoczyna kopię konfiguracji, potem danych aplikacji, na końcu zrzuty baz.

3) Po zakończeniu pakuje artefakty, opcjonalnie szyfruje, generuje sumy i log.

4) Weryfikuje integralność wybranych plików losowo z checksums.sha256.

5) Przesyła kopię poza serwer (np. rclone copy do S3).

6) Usuwa lock i zwraca kod 0; w razie błędu wysyła alert i zostawia artefakty diagnostyczne.

Checklist przed wdrożeniem

  • Określ RPO/RTO i zrób próbny cykl kopii oraz odtwarzania.
  • Upewnij się, że ścieżki i uprawnienia są bezwzględne i restrykcyjne.
  • Włącz logowanie, alerty e-mail i rotację logów.
  • Dodaj szyfrowanie tam, gdzie kopie wyjdą poza zaufaną strefę.
  • Zapewnij retencję i sprzątanie starych kopii.
  • Przetestuj scenariusz „awaria w połowie” i popraw idempotencję skryptu.

Włączając te elementy krok po kroku, zbudujesz stabilny łańcuch ochrony danych: od regularnego planu zadań przez powtarzalny proces tworzenia kopii po przejrzyste mechanizmy kontroli i odtwarzania. Dzięki temu nawet w trudnych sytuacjach technicznych odzyskasz usługę szybko i bez chaosu.

< Powrót

Zapisz się do newslettera


Zadzwoń Napisz