Ściąga SSH — sekwencje ucieczki i ratowanie sesji
Zasada działania#
Sekwencje ucieczki przechwytuje lokalny klient SSH, zanim cokolwiek poleci do sieci. Dlatego działają nawet wtedy, gdy połączenie z serwerem jest martwe.
Trzy rzeczy do zapamiętania
- Sekwencje działają wyłącznie na początku linii - zawsze najpierw Enter.
- Znaków ~ i kolejnego klawisza nie widać na ekranie - to normalne.
Ratowanie zawieszonej sesji#
| Sytuacja | Sekwencja |
|---|---|
| Terminal wisi, Ctrl+C nie działa | Enter ~ . |
| Sesja w sesji (SSH wewnątrz SSH) | Enter ~ ~ . |
| Chcę odłożyć sesję na chwilę | Enter ~ Ctrl+Z, powrót przez fg |
| Nie pamiętam skrótów | Enter ~ ? |
Reguła zagnieżdżenia: liczba tyld = jak głęboko w łańcuchu sięgasz.
~. zamyka zawsze pierwsze (najbardziej zewnętrzne) połączenie - czyli wszystko.
Odwrotnie: żeby dobić się do najgłębszej sesji (np. 3 SSH w SSH w SSH), trzeba dać
~~~. - każda dodatkowa tylda „przebija” jedną warstwę klientów po drodze.
Pełna lista sekwencji#
| Sekwencja | Działanie |
|---|---|
~. |
Rozłącz sesję |
~^Z |
Uśpij SSH w tle |
~# |
Lista przekierowanych połączeń |
~& |
Przenieś SSH w tło przy wylogowaniu |
~? |
Pomoc — lista sekwencji |
~B |
Wyślij BREAK do zdalnej strony |
~C |
Otwórz linię poleceń klienta SSH |
~R |
Wymuś ponowną wymianę kluczy (rekeying) |
~V / ~v |
Zmniejsz / zwiększ poziom logowania |
~~ |
Wyślij dosłowną tyldę |
~C - zmiana przekierowań w locie#
Pozwala dodać lub usunąć forwarding bez rozłączania sesji. Po Enter ~ Shift+C
pojawia się znak zachęty ssh>, w którym wpisujesz:
-L 8080:localhost:80 # lokalne przekierowanie
-R 2222:localhost:22 # zdalne przekierowanie
-D 1080 # dynamiczne (SOCKS proxy)
-KL 8080 # usuń przekierowanie lokalne
-KR 2222 # usuń przekierowanie zdalne
-KD 1080 # usuń dynamiczne
Uwaga
~C działa tylko na sesji, która faktycznie ma otwarty kanał do klienta
(nie zadziała przez multiplekser innej sesji - patrz zarządzanie multiplekserem).
Gdy ~. nie działa#
- Naciśnij Enter jeszcze raz i powtórz - najczęstsza przyczyna: linia nie była pusta.
- Program pełnoekranowy (
vim,less,top) - kilka razy Enter, potem sekwencja. - Dead key na klawiaturze (układ DE/FR/ES) - naciśnij ~, a potem Space, żeby tylda faktycznie została wysłana.
- Wyłączony escape char (
ssh -e none) - sekwencje nie działają w ogóle. - ControlMaster (multipleksowanie) - sekwencje ucieczki obsługuje proces-master,
nie sesja potomna. Jeśli
~.w sesji potomnej nic nie robi, zamknij ją z osobnego terminala poleceniemssh -O exit user@host.
Awaryjnie, z drugiego terminala:
$ pkill -f "ssh user@host"
Wyłączanie / zmiana znaku ucieczki#
$ ssh -e none user@host # wyłącz całkowicie
$ ssh -e '^]' user@host # zmień na Ctrl+]
Na stałe:
Host *
EscapeChar ~
Wyłączenie przydaje się przy przesyłaniu danych binarnych przez tunel.
Co dzieje się ze zdalnym procesem#
~. zabija lokalnego klienta, ale nie sprząta po stronie serwera.
Zdalny sshd zauważy zerwanie dopiero po swoim timeoucie i wyśle SIGHUP procesom w sesji -
proces uruchomiony na pierwszym planie najpewniej zginie.
Dlatego długie zadania uruchamiaj w tmux / screen:
$ tmux new -s robota # start
$ tmux attach -t robota # po rozłączeniu: powrót, zadanie leci dalej
Zapobieganie zwisom#
Wisząca sesja to zwykle brak keepalive:
Host *
ServerAliveInterval 30
ServerAliveCountMax 3
TCPKeepAlive yes
Klient co 30 s pyta serwer, czy żyje. Po trzech nieudanych próbach zrywa połączenie — czyli po ~90 sekundach zamiast po kilkunastu minutach timeoutu TCP.
Po stronie serwera odpowiednikiem jest:
ClientAliveInterval 30
ClientAliveCountMax 3
Przydatne opcje połączenia#
| Opcja | Zastosowanie |
|---|---|
ssh -v / -vvv |
Diagnostyka problemów z połączeniem |
ssh -N |
Bez zdalnego shella (sam tunel) |
ssh -f |
Przejdź w tło po uwierzytelnieniu |
ssh -J host1 host2 |
Jump host (ProxyJump) |
ssh -o "ControlMaster=auto" |
Multipleksowanie połączeń |
Multipleksowanie na stałe - kolejne sesje do tego samego hosta zestawiają się natychmiast:
Host *
ControlMaster auto
ControlPath ~/.ssh/cm-%r@%h:%p
ControlPersist 10m
Zarządzanie multiplekserem#
Gdy sesje idą przez ControlMaster, sekwencje ucieczki (~.) działają nietypowo,
bo wiele „sesji” to w rzeczywistości jedno połączenie TCP z procesem-masterem.
Zamiast tego steruje się flagą -O:
$ ssh -O check user@host # czy master żyje i jaki ma PID
$ ssh -O stop user@host # master przestaje przyjmować nowe sesje, istniejące działają
$ ssh -O exit user@host # zamknij master i wszystkie sesje na nim oparte
$ ssh -O forward user@host # dołóż forwarding zdefiniowany dodatkowymi -L/-R/-D
Przydatne, gdy ControlPersist trzyma martwe połączenie (np. po zmianie IP serwera)
i nowe próby połączenia zawisają na starym gnieździe - ssh -O exit czyści to bez
czekania na timeout.