Przejdź do treści
Lekcja 77 z 117

Kurs › Moduł 8 › Lekcja 77

Archiwa i kopiowanie przez sieć

⏱ ok. 9 min czytania· moduł 8: Sieć

Po tej lekcji: kursant pakuje i rozpakowuje archiwa tar z kompresją gzip, bzip2 i xz, zagląda do nich bez rozpakowywania, obsługuje zip, a foldery synchronizuje przez sieć rsync-iem, najpierw na próbę, potem naprawdę.

Wstęp

folder zdjecia_wakacje_FINAL_v2_naprawde_final, 4000 plików, pasek kopiowania „pozostało: 3 godziny”

Dwa scenariusze z życia. Pierwszy: musisz wysłać koledze cały folder projektu. Cztery tysiące plików. Wysyłasz je pojedynczo i po godzinie kolega pyta, czemu ma tylko połowę. Drugi: co noc robisz kopię serwera na drugi serwer. Pięćdziesiąt gigabajtów. Kopiujesz wszystko od nowa, choć zmieniło się dziesięć plików.

Na pierwszy problem jest pudło: archiwum, czyli wszystko w jednym pliku, a do tego ściśnięte. Na drugi jest rsync, który kopiuje tylko to, co się zmieniło. Dziś poznasz oba, a w zadaniu zrobisz swoją pierwszą prawdziwą kopię zapasową z maszyny na maszynę.

tar: karton na przeprowadzkę

Przeprowadzka. Nie nosisz każdej łyżeczki osobno do samochodu. Pakujesz kuchnię do kartonu, podpisujesz „kuchnia” i nosisz jeden karton. tar to właśnie taki karton: skleja wiele plików i folderów w jeden plik, razem z uprawnieniami, właścicielami i datami. Nazwa pochodzi od „tape archive”, archiwum na taśmę, bo kiedyś pakowało się tak dane na taśmy magnetyczne.

Sam tar nie zmniejsza danych. Karton z książkami waży tyle, co książki. Dlatego zwykle pakujemy i od razu kompresujemy, czyli wyciskamy powietrze. Jak worek próżniowy na kołdrę.

Pakowanie:

tar -czf projekt.tar.gz projekt

Litery czytasz jak zdanie: c jak create, utwórz. z jak gzip, ściśnij. f jak file, do pliku o nazwie… i zaraz po f musi stać nazwa archiwum. Potem to, co pakujesz.

Zajrzenie do kartonu bez rozpakowania:

tar -tzf projekt.tar.gz
projekt/
projekt/src/
projekt/src/start.sh
projekt/docs/
projekt/docs/liczby.txt
projekt/docs/services

t jak „table of contents”, spis treści. Z v dostaniesz szczegóły jak w ls -l:

tar -tvzf projekt.tar.gz
drwxr-xr-x root/root         0 2026-11-03 16:32 projekt/
drwxr-xr-x root/root         0 2026-11-03 16:32 projekt/src/
-rw-r--r-- root/root        21 2026-11-03 16:32 projekt/src/start.sh

Rozpakowanie, x jak extract, wyciągnij. -C mówi, gdzie:

tar -xzf projekt.tar.gz -C /tmp/rozpakowane
tar -xzf projekt.tar.gz -C /tmp/rozpakowane projekt/src/start.sh   # tylko jeden plik

Bez -C tar wysypuje zawartość tam, gdzie stoisz. Dlatego zanim rozpakujesz cudze archiwum, najpierw -t. Bywają archiwa, które zamiast jednego porządnego folderu wysypują trzysta plików prosto na Twoje biurko.

Pakowanie bez śmieci, przez --exclude:

tar -czf bez-txt.tar.gz --exclude='*.txt' projekt

Ubuntu] [RHEL] tar jest wszędzie taki sam, to GNU tar. Na Macu jest bsdtar, który rozumie te same podstawowe litery. [macOS

Trzy worki próżniowe: gzip, bzip2, xz

Do tara możesz dobrać jeden z trzech kompresorów. Zmierzyłem je na tym samym archiwum 380 MB z bibliotekami Pythona:

kompresor  litera  plik             rozmiar   czas
gzip       -z      duzy.tar.gz      115 MB    16,5 s
bzip2      -j      duzy.tar.bz2      95 MB    29,9 s
xz         -J      duzy.tar.xz       75 MB   173,5 s

gzip to szybki kucharz od kanapek: nie najlepiej, ale od razu. xz to szef kuchni od risotto: wynik najlepszy, ale poczekasz. bzip2 siedzi pośrodku. Na co dzień gzip, do archiwów, które leżą latami, xz. Na ćwiczenie dobrze zapamiętać: z to gzip, j to bzip2, duże J to xz.

tar -cjf projekt.tar.bz2 projekt
tar -cJf projekt.tar.xz projekt
tar -xf projekt.tar.xz -C /tmp/rozpakowane

Przy rozpakowywaniu GNU tar sam rozpozna kompresję, więc -xf wystarczy. Przy pakowaniu literę musisz podać.

Kompresory działają też same, na pojedynczych plikach:

gzip l.txt          # robi l.txt.gz, oryginał znika
gzip -l l.txt.gz    # ile zaoszczędzono
zcat l.txt.gz | tail -1
gunzip l.txt.gz     # z powrotem
gzip -k l.txt       # -k: keep, zostaw oryginał
bzip2 -k l.txt; xz -k l.txt
ls -l l.txt*
         compressed        uncompressed  ratio uncompressed_name
              45010              108894  58.7% l.txt
20000
-rw-r--r-- 1 root root 108894 Nov  3 16:32 l.txt
-rw-r--r-- 1 root root  25147 Nov  3 16:32 l.txt.bz2
-rw-r--r-- 1 root root  45010 Nov  3 16:32 l.txt.gz
-rw-r--r-- 1 root root   4948 Nov  3 16:32 l.txt.xz

Uwaga na pułapkę: gzip plik bez -k kasuje oryginał. To nie błąd, to taka filozofia. Do rozpakowania: gunzip, bunzip2, unxz. Do czytania bez rozpakowania: zcat, zless, zgrep, a dla xz xzcat. Logi w /var/log są często spakowane gzipem, więc zgrep przyda Ci się szybciej, niż myślisz.

zip: dla kolegi z Windowsem

Kolega z działu sprzedaży nie ma pojęcia, co to .tar.gz, i otworzy to najwyżej Notatnikiem. Dla niego jest zip, który rozumie każdy system:

zip -r projekt.zip projekt
unzip -l projekt.zip
unzip projekt.zip -d /tmp/z
  adding: projekt/ (stored 0%)
  adding: projekt/src/start.sh (stored 0%)
  adding: projekt/docs/liczby.txt (deflated 59%)
Archive:  projekt.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
       21  2026-11-03 16:32   projekt/src/start.sh
   108894  2026-11-03 16:32   projekt/docs/liczby.txt

-r jak rekurencja, razem z podfolderami. unzip -l to spis treści, -d to folder docelowy. Na serwerze trzymaj się tar, bo zip nie zawsze wiernie odtwarza linuksowe uprawnienia, właścicieli i dowiązania.

[Ubuntu] sudo apt install zip unzip, [RHEL] sudo dnf install zip unzip, jeśli ich brakuje.

rsync: kopiowanie, które myśli

cp i scp to tragarze: każą przenieść, przenoszą wszystko. rsync to tragarz z listą. Najpierw sprawdza, co już stoi w nowym mieszkaniu, i nosi tylko to, czego brakuje albo co się zmieniło.

rsync -av projekt/ kopia/

-a to archive, „zachowaj wszystko”: uprawnienia, właścicieli, daty, dowiązania, podfoldery. -v to verbose, gadaj, co robisz. Przez sieć wygląda to tak samo, tylko cel ma dwukropek, jak w scp:

rsync -avz ~/zdjecia web:backup/
sending incremental file list
created directory backup
zdjecia/
zdjecia/album.txt

sent 44,133 bytes  received 68 bytes  29,467.33 bytes/sec
total size is 288,894  speedup is 6.54

-z ściska dane w czasie przesyłu, przydatne przez wolne łącze. rsync sam używa SSH, więc działa Twój klucz i wpisy z ~/.ssh/config. Dopisuję jedną linijkę do pliku i puszczam drugi raz:

echo "dopisek" >> ~/zdjecia/album.txt
rsync -avz ~/zdjecia web:backup/
sent 255 bytes  received 2,514 bytes  5,538.00 bytes/sec
total size is 288,902  speedup is 104.33

Wysłane 255 bajtów zamiast 44 tysięcy. Zmieniony plik nie poleciał cały, tylko zmienione kawałki. Przy pięćdziesięciu gigabajtach kopii nocnej to różnica między „trwa całą noc” a „skończyło się, zanim zdążyłeś zrobić herbatę”.

Inny port SSH albo konkretny klucz: -e "ssh -p 2222" albo -e "ssh -i ~/.ssh/klucz". Do dużych plików -P, czyli pasek postępu i dokończenie przerwanego przesyłu od miejsca, w którym stanął.

Ukośnik, który zmienia wszystko

Teraz najważniejsza rzecz o rsync, którą każdy admin poznaje na własnej skórze.

rsync -a projekt  kopia1/
rsync -a projekt/ kopia2/
ls kopia1 kopia2
kopia1:
projekt

kopia2:
docs
src

Bez ukośnika na końcu źródła: „skopiuj folder projekt”, więc w środku kopia1 jest folder projekt. Z ukośnikiem: „skopiuj zawartość folderu projekt”. Jedna kreska, inny wynik. Zapamiętaj: ukośnik to „to, co w środku”.

--delete i -n, czyli lustro i próba generalna

Zwykły rsync tylko dodaje i aktualizuje. Jak usuniesz plik u siebie, w kopii zostanie. Żeby kopia była lustrem, dodajesz --delete. I tu robi się groźnie, bo --delete z pomylonym ukośnikiem albo zamienionymi stronami potrafi wyczyścić cel do zera. Dlatego zawsze najpierw próba generalna, -n, czyli dry run:

rsync -av --delete -n projekt/ kopia2/
sending incremental file list
deleting docs/services
docs/
src/
src/nowy.sh

total size is 108,920  speedup is 455.73 (DRY RUN)

(DRY RUN) znaczy: nic nie zostało zrobione, tylko pokazane. Widzisz, że usunie docs/services i doda src/nowy.sh. Zgadza się z tym, czego chcesz? Dopiero wtedy ta sama komenda bez -n. Jak przymiarka w przebieralni, zanim przytniesz spodnie.

Jak to działa pod spodem

tar zapisuje pliki jeden za drugim: nagłówek z nazwą, uprawnieniami, właścicielem i datą, potem zawartość, potem następny. Kompresja jest osobnym programem, przez który ten strumień przepływa. tar -czf to w praktyce tar i gzip połączone rurą. Można to zrobić dosłownie i przy okazji przenieść karton przez SSH bez pliku pośredniego:

tar -czf - projekt2 | ssh web "tar -xzf - -C /tmp && ls /tmp/projekt2"
docs
src

Minus zamiast nazwy pliku znaczy „pisz na standardowe wyjście” albo „czytaj ze standardowego wejścia”. Taśma w fabryce w najczystszej postaci.

Przy pakowaniu ścieżek bezwzględnych tar ostrzega:

tar: Removing leading `/' from member names

To dla Twojego bezpieczeństwa. Archiwum /etc zapisuje się jako etc/..., a nie /etc/..., więc rozpakowanie nie nadpisze Ci prawdziwego /etc, tylko utworzy folder etc tam, gdzie stoisz.

rsync po obu stronach uruchamia swój program. Dla każdego pliku najpierw porównuje rozmiar i datę modyfikacji. Jeśli są takie same, pomija plik. Jeśli różne, dzieli plik po stronie odbiorcy na bloki, liczy ich sumy kontrolne, a nadawca wysyła tylko bloki, których sumy się nie zgadzają. Stąd te 255 bajtów zamiast 44 tysięcy.

Ściąga flag

KomendaFlagaCo robi
tar-c / -x / -tutwórz / rozpakuj / pokaż spis
tar-f pliknazwa archiwum, zawsze zaraz po f
tar-z / -j / -Jgzip / bzip2 / xz
tar-vwypisuj pliki
tar-C folderrozpakuj do folderu (albo pakuj z folderu)
tar--exclude='wzór'pomiń pasujące pliki
gzip / bzip2 / xz-kzostaw oryginał
gzip-l / -dstatystyka / rozpakuj
zcat / xzcat—czytaj spakowany plik bez rozpakowania
zip-rpakuj z podfolderami
unzip-l / -d folderspis / rozpakuj do folderu
rsync-aarchiwum: uprawnienia, daty, podfoldery
rsync-v / -zgadaj / ściskaj w przesyle
rsync--deleteusuwaj w celu to, czego nie ma w źródle
rsync-npróba generalna, nic nie zmienia
rsync-Ppostęp i wznawianie przerwanych plików
rsync-e "ssh -p 2222"własne ustawienia SSH

⚠ Typowy błąd

Pomylona kolejność liter w tar:

tar -cfz kopia.tar.gz projekt
tar: kopia.tar.gz: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors

„Nie mogę znaleźć pliku kopia.tar.gz”. Jak to, przecież to miała być nazwa archiwum? Nie. Po f musi stać nazwa archiwum, a stoi z. Więc tar utworzył archiwum o nazwie z, bez kompresji, i próbował do niego zapakować plik kopia.tar.gz, którego nie ma, oraz folder projekt:

ls -l z
file z
-rw-r--r-- 1 root root 133120 Nov  3 16:32 z
z: POSIX tar archive (GNU)

Gorsza wersja tego samego: tar -czf skrypt.sh projekt przy pomylonej kolejności argumentów nadpisuje Ci skrypt.sh archiwum. Bez pytania. Zasada: f zawsze na końcu grupy liter, zaraz po nim nazwa archiwum, a dopiero potem to, co pakujesz. -czf, nie -cfz.

✎ Zadanie

Z jednej maszyny wirtualnej zrób kopię folderu /etc na drugą przez rsync po SSH z logowaniem kluczem. Potem zrób archiwum etc-DATA.tar.gz z dzisiejszą datą w nazwie i wypisz jego zawartość bez rozpakowywania.

Pokaż rozwiązanie

Zadanie było takie: skopiować /etc z jednej maszyny na drugą przez rsync po SSH z kluczem, a potem zrobić archiwum z datą w nazwie i zajrzeć do niego bez rozpakowywania.

# na maszynie 1 (klucz już jest na maszynie 2 z odcinka 76)
sudo rsync -az -e "ssh -i /home/eryk/.ssh/id_ed25519" /etc/ eryk@vm2:kopia-etc/

Ukośnik na końcu /etc/ znaczy „zawartość folderu”, nie sam folder. -a zachowuje uprawnienia, daty i dowiązania, -z kompresuje w drodze. Po co sudo? Bo w /etc są pliki, których zwykły użytkownik nie przeczyta, na przykład /etc/shadow. I tu jest haczyk, na którym wykłada się każdy. Kiedy piszesz sudo rsync, SSH uruchamia się jako root i szuka kluczy roota, w /root/.ssh, a nie Twoich. Dlatego podajesz klucz wprost przez -e "ssh -i …". Bez tego dostajesz pytanie o hasło i podejrzenie, że klucze to jakaś ściema.

Number of created files: 1,904 (reg: 713, dir: 296, link: 895)
...
sent 1,261,039 bytes  received 17,515 bytes  852,369.33 bytes/sec
total size is 7,395,375  speedup is 5.78

Drugi haczyk widać po drugiej stronie:

-rw-r----- 1 eryk eryk 1613 Nov  3 16:27 kopia-etc/shadow

Plik z hasłami roota należy teraz do zwykłego użytkownika na drugiej maszynie. Kopia /etc to kopia sejfu. Trzymaj ją tam, gdzie nikt postronny nie zagląda.

Archiwum:

sudo tar -czf "etc-$(date +%F).tar.gz" -C / etc
tar -tzf etc-2026-11-03.tar.gz | head -3
etc/
etc/rc2.d/
etc/rc2.d/S01autofs

-C / każe najpierw wejść do /, więc w archiwum ścieżki są względne, etc/…, bez ukośnika na początku. Przy rozpakowaniu nic nie nadpisze Ci prawdziwego /etc. Archiwum, które przy rozpakowaniu nadpisuje system, to nie kopia zapasowa, tylko bomba z opóźnionym zapłonem.

Co dalej

Sieć mamy za sobą: konfiguracja, diagnostyka, porty, zapory, routing, podsłuch, SSH i kopie. W następnej lekcji zajmiemy się ludźmi: użytkownicy i grupy, czyli kto w ogóle ma prawo wejść do tego budynku i do których pokojów dostaje klucze.