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.
Spis treś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.