Resetowanie i testowanie połączenia sieciowego z linii komend

Być może tak jak ja masz sieć bezprzewodową, która czasem wariuje i połączenie pada. Pomaga zaś proste rozłączenia się i połączenie ponownie. Nie mogę obiecać pewnego sposobu na uporanie się z każdą możliwą przyczyną takiego stanu, ale mogę podzielić się linuksowym skryptem, który pozwala zredukować do minimum ręczne czynności. Użyjemy nmcli, czyli konsolowego interfejsu do Network Managera. Przy okazji trzeba jednak uważać, by nie popsuć sobie kontenerów Dockera.

Wyjaśnię też, czemu warto używać curla (a nie pinga) do testowania dostępności sieci, zarówno na własnej maszynie, jak i w kontenerach Dockera na CI.

Potrzeba

Moja domowa sieć bezprzewodowa nie jest może najgorsza, ale ma irytującą właściwość: od czasu do czasu połączenie pada w paskudny sposób. Nie chodzą żadne pingi, za da się słuchać strumieniowanego radia albo muzyki. Obstawiałem fatalne serwery DNS po stronie dostawcy Internetu (więcej o tym, co te firmy potrafią wyprawiać, opisałem w artykule Gdy DNS nie pozwala połączyć się z chmurą AWS). Tyle że ustawienie statycznych serwerów DNS innego pochodzenia nie usunęło całkowicie niestabilności.

Z drugiej strony, problem pojawia się niezbyt często. Rzeczą, której żal mi najbardziej, nie jest czas, jaki poświęcam za każdym razem na naprawienie go (kliknij rozłącz, poczekaj, kliknij połącz). Dla mnie najgorsze jest rozproszenie: trzeba skupić uwagę na kliknięciu w odpowiedniej sekwencji w odpowiednie miejsca, uważnie obserwować zmieniającą się podczas rozłączania listę sieci. Ja natomiast, jak już pisałem wiele razy na blogu, uważam, że warto rozproszenia jak się tylko da ograniczać.

Dobry sposób

Lepszym z punktu widzenia produktywności rozwiązaniem jest skrypt: uruchamiamy jedną rzecz, a tam już dzieje się, co trzeba. Może szybciej, może wolniej, ale nie trzeba tego pilnować. Lepiej nawet przez parę sekund popatrzeć bezczynnie przez okno na chmury, niż przez ten sam czas czekać, aż lista wyświetli sieć dostępną do połączenia. Nie mówiąc o tym, że dużo rzeczy w IDE można zrobić bez dostępu do Internetu.

nmcli radio wifi off && \
    sleep .5 && \
    radio wifi on

Próba połączenia od razu po rozłączeniu się czasem się nie udaje, stąd umieszczona w środku pauza na pół sekundy. Z tą pauzą skrypt działa niezawodnie.

O jedną sieć za daleko

Początkowo kod wyglądał inaczej.

nmcli n off && \
    sleep .5 && \
    nmcli n on

Skrypt po prostu wyłączał całą komunikację sieciową, a potem włączał ponownie. Wszystko działało dobrze przez długi czas. Dopóki pewnego dnia moja skonteneryzowana baza nie przestała odpowiadać. Kilka minut wcześniej wszystko działało, a tu nagle nic. Chwilę zajęło mi rozgryzienie przyczyny: że nmcli networking off ubijał też sieci stawiane przez docker compose, a nmcli networking on wcale ich nie podnosił z powrotem. Też trochę czasu spędziłem na rozgryzieniu, czemu docker compose start nie jest w stanie naprawić stanu rzeczy (StackOverflow: What is the difference between docker-compose up and docker-compose start?).

Ostateczny skrypt

Wspomniany wcześniej skrypt umieściłem w ~/bin/reset-wifi:

nmcli radio wifi off && \
    sleep .5 && \
    radio wifi on

Nie używam go jednak bezpośrednio. Zauważyłem, że czasem niepotrzebnie resetuję sieć – mnie wydaje się, że padło moje WiFi, gdy naprawdę problem jest jedynie z jedną stroną, z której korzystam. Podejmowanie decyzji (czy to sieć czy tylko strona?) to też obciążenie i rozproszenie, więc postanowiłem zdjąć z siebie ten obowiązek i przenieść na coś automatycznego. Wołam skrypt ~/bin/check-wifi:

curl wp.pl --max-time 1.1 -o /dev/null --silent --show-error || $HOME/bin/reset-wifi

Nie sprawdzam stanu sieci przez ping ani dig, bo w sumie nie interesuje mnie, czy padł sam DNS, a działa „gołe” TCP. curl robi test „end to end”: tłumaczenie adresu i transfer danych mają działać w ciągu 1,1 sekundy, bez rozdrabniania się na connection timeout itp.

Działanie proaktywne: cron

Zamiast czekać, aż coś się zepsuje i wtedy uruchamiać skrypt, można też wykonywać go regularnie, wykorzystując wbudowane narzędzie Linuksa, czyli cron. Nie wymaga to uprawnień roota.

crontab -e

uruchamia edytor tekstowy do edycji naszego crontaba. Dla mojego skryptu dodaję linijkę:

*/5 * * * * /home/piotr/bin/wifi-check >> /tmp/wifi-check.log

Linijkę zaczyna wyrażenia crona (do sprawdzenia na https://crontab.guru, moje oznacza „co 5 minut”), dalej podaję komendę. Żeby wiedzieć, co robi mój skrypt, wyjście przekierowuję do pliku. Skrypt należy trochę zmienić, żeby produkował sensowne logi:

if ( curl wp.pl --max-time 1.1 -o /dev/null --silent --show-error ); then
    echo $(date) connection ok
else
    echo $(date) resetting connection
    $HOME/bin/reset-wifi
fi

Dodatkowa lektura

Więcej o nmcli można poczytać na przykład w ArchWiki. Zdecydowanie warto znać to narzędzie.

curl z opcją --max-time jest też dobrym narzędziem do użycia w CI, by sprawdzić, czy działa sieć, albo czy wstał serwer. Popularne obrazy Dockera (jak openjdk:17.0-jdk-bullseye) mają zainstalowanego curla.

Creative Commons License
Except where otherwise noted, the content by Piotr Kubowicz is licensed under a Creative Commons Attribution 4.0 International License.