Pobieraj wgetem do pliku tymczasowego, nie prosto na miejsce docelowe - istniejący plik docelowy wget ucina od razu po starcie transferu. Po pobraniu sprawdź status procesu, porównaj sumę kontrolną SHA-256 z wartością od producenta i dopiero wtedy przenieś plik. Błędu TLS nie naprawiaj opcją --no-check-certificate.

Piątek, w którym wget skasował działającą binarkę

Adam sam utrzymuje serwer aplikacji w dwuosobowej firmie. To fikcyjny przykład, ale każde zachowanie wgeta w nim jest prawdziwe i opisane w manualu programu.

W piątek po południu wyszła nowa wersja narzędzia, z którego korzysta aplikacja, więc Adam podmienił je jedną komendą, prosto na miejsce: wget --output-document=/usr/local/bin/narzedzie URL. W połowie transferu padło połączenie. Wget zakończył się błędem sieci, ale stara, działająca binarka już wtedy nie istniała - --output-document ucina wskazany plik na starcie, nie po udanym pobraniu. Na dysku został fragment nowej wersji, a aplikacja wstała dopiero po odtworzeniu pliku z kopii.

Tydzień później jego wspólniczka Marta pobierała archiwum z aktualizacją. Transfer zakończył się statusem zero, plik leżał na dysku, więc poszedł do wdrożenia. Po awarii okazało się, że serwer w sieci wydał inną treść, niż opublikował producent - a nikt nie porównał sumy kontrolnej z wartością z jego strony. Status, log i plik na dysku mówiły „pobrano". Żaden nie mówił „pobrano to, co trzeba".

Obie wpadki mają wspólne źródło: skrót myślowy „wget się skończył, więc plik jest dobry". Poniższy wzorzec rozbija to na osobne pytania i każe odpowiedzieć na każde z nich osobno.

Jak wygląda bezpieczny wzorzec pobrania?

Polecenia wykonuj na hoście, na którym plik ma docelowo pracować. Zacznij od sprawdzenia narzędzia i miejsca na dysku:

wget --version
df -h /sciezka/do/katalogu

Pierwsza komenda wypisuje wersję i kończy działanie bez pobierania. Druga raportuje zajętość systemu plików, na którym stanie katalog roboczy. /sciezka/do/katalogu zastąp katalogiem przeznaczonym na plik tymczasowy.

Zanim ruszysz z transferem, możesz zapytać serwer o sam zasób, bez zapisywania treści:

wget --spider --server-response URL_ZRODLOWY

--spider sprawdza obecność zasobu, a --server-response wypisuje odpowiedź serwera. Ten krok niczego nie pobiera, więc nie potwierdza ani treści pliku, ani tego, że właściwy transfer się powiedzie - to będzie osobne żądanie, wykonane później.

Właściwe pobranie przygotuj w trzech decyzjach:

  1. Ustal URL_ZRODLOWY z kanału publikacji producenta - ze strony wydań, nie z przypadkowej kopii.
  2. Wybierz trzy oddzielne ścieżki: plik tymczasowy, log i plik docelowy.
  3. Nazwij plik tymczasowy dokładnie tak, jak nazwał go producent w pliku sumy - sha256sum --check szuka pliku po tej nazwie.

Potem pobierz plik i zachowaj komunikaty procesu:

wget --server-response \
  --output-document=/sciezka/do/katalogu-tymczasowego/NAZWA_PLIKU \
  URL_ZRODLOWY \
  > /sciezka/do/LOG_WGET 2>&1

Po zakończeniu odczytaj status procesu, na przykład przez echo $? bezpośrednio po komendzie. Niezerowy status to błąd - nie przenoś wtedy pliku tymczasowego dalej. Problem został w katalogu roboczym i tam masz go obejrzeć, z logiem w ręku.

Jeśli producent publikuje plik z sumami w formacie zgodnym z sha256sum, pobierz go osobno z kanału producenta, połóż w tym samym katalogu roboczym i uruchom kontrolę:

(cd /sciezka/do/katalogu-tymczasowego && sha256sum --check PLIK_SUMY)

Jeżeli plik sum wymienia więcej pozycji, kontrola wymaga obecności wszystkich wskazanych plików - brak którejkolwiek daje wynik niezerowy. Po zgodnym wyniku przenieś plik na miejsce:

mv /sciezka/do/katalogu-tymczasowego/NAZWA_PLIKU /sciezka/do/PLIKU_DOCELOWEGO

To mv jest jawnym momentem przekazania pliku do kolejnego etapu. Samo przeniesienie nie uruchamia pliku ani nie dowodzi, że działa - to sprawdza już wdrożenie, nie pobieranie.

Co potwierdza każdy sygnał?

Zanim uwierzysz komunikatowi „pobrano", ustal, na które pytanie ten komunikat w ogóle odpowiada. Każdy wiersz tabeli to inne pytanie.

Sygnał Co potwierdza Czego nie potwierdza Co zrobić przy błędzie
wget --spider --server-response zasób istnieje, serwer odpowiedział treści pliku, integralności, powodzenia późniejszego transferu popraw URL albo obejrzyj odpowiedź serwera; nie twórz pliku docelowego
log z --server-response jakie nagłówki odesłał serwer podczas pobierania zgodności bajtów z tym, co opublikował producent zachowaj log i czytaj go razem ze statusem procesu
status procesu 0 wget nie zgłosił problemu ze swojego zakresu integralności, pochodzenia ani działania pliku dla 1-8 zakończ zadanie błędem i odczytaj klasę problemu
plik istnieje na dysku treść zapisała się pod wskazaną ścieżką kompletności ani zaufanego pochodzenia nie przenoś pliku, jeśli proces zakończył się błędem
sha256sum --check zgodny bajty pliku odpowiadają sumie z pliku sum niczego, jeśli suma nie przyszła niezależnym, zaufanym kanałem zatrzymaj wdrożenie i wyjaśnij rozbieżność przed kolejnym pobraniem

Dlaczego nie pobierać prosto na miejsce docelowe?

--output-document kieruje całą pobieraną treść do jednego wskazanego pliku i działa jak przekierowanie wyjścia w powłoce: istniejący cel ucina natychmiast, jeszcze zanim transfer się zakończy. Awaria sieci albo odpowiedź błędowa serwera zostawia wtedy w miejscu działającego pliku ucięty fragment - dokładnie to spotkało Adama.

Dlatego celem pobrania jest plik w katalogu roboczym, a nie konfiguracja, binarka czy archiwum, z których proces wdrożenia nadal korzysta. Nieudany transfer zostaje wtedy poza aktywną ścieżką, a do mv dochodzi dopiero po ocenie statusu i kontroli sumy.

Ta sama zasada obowiązuje przy ponowieniu zadania. Każde kolejne uruchomienie z tym samym --output-document znowu utnie wskazany cel, zanim cokolwiek pobierze.

Jak wznowić przerwane pobieranie?

Opcja --continue dociąga częściowy plik, o ile serwer obsługuje pobranie od wskazanego miejsca. Wget nie umie sprawdzić, czy lokalny fragment jest prawidłowym początkiem zdalnego pliku - dlatego wznawiaj tylko wtedy, gdy producent publikuje sumę kontrolną, którą końcowy plik zweryfikujesz.

(cd /sciezka/do/katalogu-tymczasowego && \
  wget --continue --server-response URL_ZRODLOWY \
    > /sciezka/do/LOG_WGET 2>&1)

Wznowienie zadziała pod dwoma warunkami: URL wskazuje ten sam plik, którego fragment leży w katalogu, a nazwa wyprowadzana przez wget z URL-a jest identyczna z nazwą tego fragmentu. Nie łącz --continue z --output-document w tej procedurze. Gdy serwer nie obsługuje wznowienia, wget zaczyna transfer od zera i nadpisuje istniejący plik.

Status zero po wznowieniu wciąż nie dowodzi spójności. Dopiero zgodny wynik sha256sum --check pozwala przenieść plik - bez niego zostaje tymczasowy.

Jak sprawdzić, czy plik jest ten właściwy?

sha256sum --check czyta z pliku sum oczekiwaną wartość i nazwę pliku, liczy sumę SHA-256 pobranego pliku i porównuje obie wartości. Zgodny wynik potwierdza jedno: bajty na dysku odpowiadają wartości zapisanej w pliku sum.

Cała siła tego testu leży w pochodzeniu oczekiwanej wartości. Suma musi przyjść od producenta niezależnie od pobranego pliku - wartość leżąca obok podmienionego pliku, w tym samym niezaufanym kanale, nie potwierdza niczego. Nie licz też sumy pobranego pliku po to, żeby porównać ją z nią samą: taki wynik opisuje bieżący plik, ale nie wiąże go z tym, co opublikował producent.

Mechaniki testu pilnują dwie rzeczy: nazwa zapisana w PLIK_SUMY musi być identyczna z nazwą pliku w katalogu roboczym, a kontrolę uruchamiasz z katalogu, względem którego zapisano ścieżki. Wynik dotyczy wyłącznie plików wskazanych w pliku sum - o reszcie wdrożenia nie mówi nic.

Co znaczy niezerowy status wget?

Status procesu kieruje cię do klasy problemu, a log i odpowiedź serwera zawężają diagnozę:

  • 1 - błąd ogólny;
  • 2 - błąd parsowania opcji;
  • 3 - błąd wejścia lub wyjścia pliku;
  • 4 - awaria sieci;
  • 5 - błąd weryfikacji SSL;
  • 6 - błąd uwierzytelnienia;
  • 7 - błąd protokołu;
  • 8 - błędna odpowiedź serwera.

Przy statusie 5 pada najgroźniejsza pokusa tej procedury. Nie naprawiaj błędu TLS opcją --no-check-certificate: wyłącza ona zarówno kontrolę certyfikatu, jak i zgodności nazwy hosta, więc połączenie przestaje weryfikować, z kim rozmawia. Napraw źródło zaufania - magazyn certyfikatów na hoście - albo nazwę hosta użytą w URL-u.

Jak wpiąć wget w cron albo skrypt wdrożeniowy?

Wget działa nieinteraktywnie, bez terminala obsługiwanego przez człowieka, więc naturalnie trafia do crona i skryptów. Zadanie automatyczne trzyma się trzech reguł:

  1. Zachowaj oba strumienie wyjścia do logu - tak jak w komendzie z procedury wyżej.
  2. Zakończ zadanie błędem po każdym niezerowym statusie; plik tymczasowy nie idzie wtedy dalej, nie jest publikowany ani uruchamiany.
  3. Przy statusie zero nadal wykonaj kontrolę sumy, jeżeli producent ją publikuje, i dopiero po zgodnym wyniku wykonaj mv.

Gdy producent nie publikuje sum, nie rozciągaj znaczenia statusu zero: wget nie zgłosił problemu, ale niczego nie porównał z wartością producenta. Warunek dopuszczenia pliku dalej musi wtedy wynikać z twojego procesu wdrożenia - na przykład z testu kolejnego etapu - a nie z samej obecności pliku na dysku.

Pytania o wget

Co to jest wget?

GNU Wget to narzędzie do nieinteraktywnego pobierania plików przez HTTP, HTTPS i FTP, umiejące też korzystać z proxy HTTP. Działa bez terminala obsługiwanego przez człowieka, więc nadaje się do skryptów i zadań cyklicznych. W tym tekście pracuje na serwerze docelowym: pobiera pojedynczy plik i zostawia status, log oraz plik do weryfikacji.

Jak pobrać plik wgetem pod wskazaną nazwą?

Użyj --output-document=/sciezka/do/pliku i pamiętaj o dwóch rzeczach. Istniejący cel wget utnie od razu po starcie, więc pobieraj do katalogu roboczego, nie na miejsce docelowe. Nazwa powinna zgadzać się z nazwą z pliku sum producenta - wtedy sha256sum --check znajdzie plik bez przekładania.

Jak sprawdzić, czy wget pobrał poprawny plik?

Wykonaj trzy sprawdzenia po kolei: status zakończenia procesu, log z odpowiedzią serwera i porównanie sumy SHA-256 z wartością opublikowaną przez producenta. Samo istnienie pliku potwierdza tylko zapis pod wskazaną ścieżką. Bez zgodnej sumy z niezależnego kanału traktuj plik jako tymczasowy i nie przenoś go do aktywnej ścieżki.

Czy --no-check-certificate naprawia błąd TLS?

Nie - ukrywa go. Opcja wyłącza kontrolę certyfikatu serwera i zgodności nazwy hosta, więc połączenie HTTPS przestaje weryfikować tożsamość drugiej strony. Napraw magazyn certyfikatów na hoście albo popraw nazwę hosta w URL-u i pobieraj dopiero wtedy, gdy weryfikacja TLS przechodzi bez wyjątków.

Czym różni się wget od rsync przy przenoszeniu plików na serwer?

Wget pobiera zasób wskazany URL-em z serwera WWW - z obcego źródła, którego nie kontrolujesz, dlatego kończy pracę kontrolą sumy. Do przenoszenia i synchronizacji własnych katalogów między dwoma hostami przez SSH służy rsync z kopiowaniem przyrostowym. Plik od zewnętrznego producenta pobieraj wgetem z weryfikacją; własne dane między swoimi serwerami przenoś rsynkiem.

Co dalej po pobraniu pliku?

Ten tekst kończy się w chwili, w której zweryfikowany plik leży na miejscu docelowym. Mirroring, czyli pobieranie kopii całej witryny, to osobny temat, a pełną listę opcji utrzymuje manual GNU Wget. Pozostałe narzędzia terminalowe do pracy z serwerem zbiera przegląd komend. Opcje, statusy i zachowania opisane wyżej pochodzą z manuala GNU Wget 1.25.0 oraz z dokumentacji GNU Coreutils dla sha256sum, df i mv.