Zrzeczenie się
Jeśli twoje połączenie SSH nie przeżywa krótkotrwałych awarii sieci, dzieje się coś innego , co nie pozwala ssh
i TCP wykonuje swoje normalne czynności.
Szczegóły poniżej. Tak czy siak:
Najszybsze i najbrudniejsze rozwiązanie bez zależności
Utwórz skrypt powłoki w następujący sposób:
#!/bin/sh -
# Tune these numbers depending on how aggressively
# you want your SSH session to get reconnected.
timeout_options='-o ServerAliveInterval=4 -o ServerAliveCountMax=2'
# 255 is the status OpenSSH uses to signal SSH errors, which
# means we want to connect. All other exit statuses suggest
# an intentional exit.
status=255
# Keep opening the SSH connection and immediately dropping into
# `screen` until an intentional exit happens.
while [ "$status" = 255 ]
do
ssh $timeout_options -t "$@" screen -dR
status=$?
# You can add a `sleep` command here or a counter or whatever
# you might need as far as rate/retry limiting.
done
exit "$status"
To po prostu uruchomi głupią, prostą pętlę, która wciąż próbuje się połączyć ssh
i dołączyć screen
. Przekaż hosta lub cokolwiek innego, co normalnie przekażesz do ssh
wywołania, jako argumenty wiersza polecenia.
Ponowne połączenie opiera się tylko na tym, czy SSH zgłasza błąd połączenia, co oznacza, że nie ma inteligencji w wykrywaniu błędów innych niż SSH, takich jak „dosłownie nie masz włączonego WiFI” lub cokolwiek innego, ale to prawdopodobnie nie ma znaczenia dla ty.
Zakładam, że masz ssh-agent
klucz SSH bez hasła, który pozwoli, aby ponowne połączenia działały bez dodatkowych danych wejściowych.
Będzie mały warunek wyścigu, w którym jeśli trafisz ^C
podczas właściwej niedostrzegalnej dla człowieka części sekundy podczas ponownego połączenia, możesz skończyć zabiciem skryptu zamiast przekazywania go ^C
do terminalu klienta, więc jeśli podejrzewasz, że połączenie się zawiesiło nie zacieraj ^C
zbyt gorliwie.
Najprostsze dodatkowe oprogramowanie
Możesz wypróbować program autossh , który powinien być dostępny w repozytorium pakietów Ubuntu.
Jeśli musisz zbudować go ze źródła lub skontrolować, jest to pojedynczy program C, który kompiluje się bez żadnych dodatkowych bibliotek jako zależności, wydaje się mieć więcej inteligencji w sprawdzaniu żywotności połączenia niż mój hack powyżej, a także jest wyposażony w wygodne rscreen
polecenie skryptowe, które automatycznie dołącza się do screen
.
Detale
Jak ssh
normalnie odzyskuje
Aby zweryfikować, bo nie lubię mówić rzeczy bez sprawdzenia siebie, przed odpowiedzią przeprowadziłem mały test:
Włączyłem WiFi z urządzeniem Linux, nawiązałem połączenie SSH z innym urządzeniem w mojej sieci LAN, zweryfikowałem, że mam działające ssh
połączenie z drugim końcem (mogłem uruchamiać polecenia itp.), A następnie na kliencie odłączyłem Wi-Fi (powodując interfejs do zdekonfigurowania: nie ma już adresów IP), wpisałem kilka kolejnych znaków do sesji ssh (oczywiście bez odpowiedzi), a następnie ponownie połączyłem się z moją siecią Wi-Fi - ponowne połączenie nie powiodło się przynajmniej raz z powodu złego sygnału i innych czynników , a potem w końcu ponownie się połączyłem: czekałem około pięciu sekund na ssh
przywrócenie sesji, nic się nie stało, więc nacisnąłem jeszcze jeden klawisz, a ssh
sesja natychmiast ożyła, a wszystkie klawisze, które wpisałem podczas rozłączania, pojawiły się w wierszu polecenia.
Widzisz, ssh
po prostu zapisuje / odczytuje w gnieździe sieciowym TCP, dopóki system operacyjny nie powie, że coś poszło nie tak, a TCP jest w rzeczywistości bardzo tolerancyjny na przedłużające się zerwanie połączenia.
Pozostawiony swoim własnym urządzeniom z domyślnymi ustawieniami jądra, stos TCP w Linuksie z radością toleruje połączenie, które zostanie całkowicie uciszone na wiele minut, zanim zadeklaruje połączenie jako martwe i zgłosi błąd ssh
- zanim w końcu się podda, rozmawiamy na boisku ~ 30 minut, a przynajmniej na pewno wystarczająco długo, aby przetrwać czkawkę połączenia trwającą sekundę lub minutę.
Jednak pod osłonami stos Linux Linux stopniowo próbuje wiadomości z coraz dłuższymi opóźnieniami, co oznacza, że zanim połączenie zostanie przywrócone, możesz spodziewać się dodatkowego opóźnienia, zanim ssh
sesja znów zacznie „ożywać”.
Dlaczego czasami się psuje
Często coś aktywnie powoduje zamknięcie połączenia po znacznie krótszym okresie bezczynności niż ilość tolerowana przez stos TCP, a następnie niezgłoszenie ssh
klientowi tego stanu połączenia .
Prawdopodobni kandydaci to:
Zapory ogniowe lub routery NAT, które muszą używać pamięci do zapamiętywania każdego połączenia TCP na żywo - jako optymalizacja i pewne ograniczenie przed atakami DOS czasami po prostu zapominają o twoim połączeniu, a następnie dyskretnie ignorują kolejne pakiety, ponieważ pakiety w środek połączenia, gdy nie pamiętasz istniejącego połączenia, wygląda nieprawidłowo.
Lepiej działające zapory ogniowe / routery wstrzykną pakiet TCP RST, który zwykle objawia się jako connection reset by peer
komunikat o błędzie, ale pakiet resetowania jest zapisem i zapomnieniem, więc jeśli połączenie z klientem nadal ma problemy w tym momencie i upuszcza zresetuj też pakiet, twój klient będzie myślał, że połączenie jest nadal aktywne.
Serwer sam może posiadać politykę zapory cicho upuść nieoczekiwane pakiety, które rozkładają wznawia połączenie prób klienta, gdy serwer myśli połączenie zamknięte, ale klient nie: klient utrzymuje próbuje kontynuować połączenie, ale serwer jest po prostu ignorując to, ponieważ nie ma połączenia na żywo, do którego te pakiety należą w stanie zapory serwera.
Ponieważ używasz Linuksa, dokładnie sprawdź na swoim serwerze iptables
/ ip6tables
(lub nft
jeśli używasz nowych rzeczy) dokładnie, na co pozwalasz, a nie upuszczając. Bardzo często zezwala się na nowe / ustanowione / powiązane pakiety na porcie TCP SSH, ale nie na „niepoprawne” - jeśli po cichu upuszczasz wszystko, co nie jest dozwolone, ta wspólna konfiguracja może powodować tego rodzaju zawieszanie się po krótkich problemach z połączeniem .
Sam serwer SSH może zostać skonfigurowany do zamykania połączenia po pewnym okresie bezczynności, przy użyciu jednej z opcji OpenSSH dla pakietów podtrzymujących klienta TCP lub SSH. Samo w sobie nie spowoduje to zawieszania się na czas nieokreślony, ale może wprowadzić cię w jeden ze stanów opisanych powyżej.
Możliwe, że po prostu nie masz wystarczająco dużo czasu na samodzielne „odczepienie” po przejściu w stan, w którym kończy się ssh
sesja.
<Enter>
i wpisz,~.
aby powiedzieć swojej stronie, aby porzuciła połączenie, a następnie możesz po prostu powtórzyć ostatnie polecenie ssh, aby połączyć się ponownie (np. Za pomocą strzałki w górę lub!!
).