Відмова від відповідальності
Якщо ваш SSH-з'єднання не переживає коротких відключень мережі, то відбувається щось інше, що не дозволяє ssh
TCP робити нормальну справу.
Детальніше дивіться нижче. У будь-якому випадку:
Найшвидше і найбрудніше рішення про незалежність
Створіть такий сценарій оболонки:
#!/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"
Це просто запустить тупо-простий цикл, який продовжує намагатися з'єднатися ssh
і приєднатися до нього screen
. Передайте хост або будь-що інше, що ви зазвичай переходите до ssh
виклику як аргументи командного рядка.
Повторне підключення ґрунтується лише на тому, чи повідомляє SSH про помилку підключення, а це означає, що він не має інтелекту для виявлення помилок, що не належать до SSH, типу "у вас буквально не ввімкнено WiFI" або будь-якого іншого, але це, ймовірно, не має значення для ти.
Я припускаю, що у вас є ssh-agent
ключ SSH або без парольної фрази, який дозволить повторно підключатися до роботи без додаткового введення від вас.
Там буде крихітна гонка, коли, якщо ви потрапите ^C
протягом лише потрібної непомітної для людини частки секунди під час повторного підключення, ви можете в кінцевому підсумку вбити сценарій замість того, щоб передавати пропуск ^C
до клієнтського терміналу, тому, якщо ви підозрюєте, що з'єднання повіситься не збивайте ^C
занадто ревно.
Найпростіше додаткове програмне рішення
Ви можете спробувати програму autossh , яка повинна бути доступна у вашому сховищі пакетів Ubuntu.
Якщо вам потрібно побудувати з джерела або перевірити його, це єдина програма C, яка збирається без додаткових бібліотек як залежностей, схоже, має більше інтелекту щодо перевірки життєздатності з'єднання, ніж мій злом вище, і він також постачається зі зручною rscreen
командою сценарію, яка автоматично -приєднується до screen
.
Деталі
Як ssh
нормально одужує
Просто для перевірки, оскільки мені не подобається говорити речі, не перевіряючи себе, я пройшов невеликий тест, перш ніж відповісти:
Я потрапив на свій WiFi з пристроєм Linux, зробив з’єднання SSH з іншим пристроєм у своїй локальній мережі, перевірив, що я працював ssh
на іншому кінці (міг запускати команди тощо), потім на клієнті відключив WiFi (викликаючи інтерфейс де-конфігуровано: більше IP-адрес), набрав ще більше символів у сеанс ssh (без відповіді, звичайно), а потім знову підключився до мого Wi-Fi - відновлення фактично не вдалось хоча б раз через поганий сигнал та інші фактори , потім нарешті знову підключились: я зачекав близько семи секунд, щоб ssh
сеанс відновився, нічого не сталося, тому я натиснув ще одну клавішу, і ssh
сеанс одразу ожив знову, при цьому всі ключі, які я набрав під час відключення, з’явились у командному рядку.
Дивіться, ssh
просто записує / читає в мережевий сокет TCP, поки ОС не каже, що щось пішло не так, а TCP насправді дуже терпимий до тривалих перепадів з'єднання.
Залишивши власні пристрої з налаштуваннями ядра за замовчуванням, стек TCP в Linux буде радісно терпіти, коли з'єднання буде повністю безшумним протягом багатьох хвилин, перш ніж оголосити про з'єднання мертвим і повідомити про помилку ssh
- до моменту, коли він остаточно відмовиться, ми говоримо в бальній частині приблизно 30 хвилин, або, принаймні, звичайно, досить довгий, щоб перетримати гикавку на зв’язку тривалістю секунди або хвилини.
Під обкладинками стек Linux TCP поступово повторює повідомлення з більш довгими та тривалими затримками, але це означає, що до моменту, коли ваше з'єднання повернеться, ви можете переглядати додаткові відставання до того, як ваш ssh
сеанс, здається, знову "оживе".
Чому це іноді ламається
Часто щось активно призводить до припинення з'єднання після деякого значно коротшого періоду бездіяльності, ніж сума, яку буде терпіти стек TCP, а потім не повідомляє про стан з'єднання своєму ssh
клієнту.
Ймовірно, кандидати включають:
Брандмауери або NAT-маршрутизатори, яким потрібно використовувати пам'ять для запам’ятовування кожного прямого TCP-з'єднання - як оптимізація та деяке пом’якшення проти DOS-атак, вони іноді просто забудуть ваше з'єднання, а потім мовчки ігнорують послідовні пакети для нього, тому що пакети в в середині з'єднання, коли ви не пам’ятаєте, що існуюче з'єднання виглядає недійсним.
Брандмауери / маршрутизатори, які краще ведуть себе, вводять пакет TCP RST, який зазвичай проявляється як connection reset by peer
повідомлення про помилку, але пакет скидання - це затримка та забуття, тому якщо підключення до вашого клієнта все ще має проблеми в цей момент і скидає скиньте пакет також, ваш клієнт подумає, що з'єднання все ще живе.
Сервер сам може мати політику брандмауера мовчазно опускаєте несподівані пакети, які будуть ламаються спроби підключення відновлення клієнта щоразу , коли сервер вважає , що з'єднання закрито , але покупець не буде : ваш клієнт продовжує намагатися продовжити з'єднання, а сервер просто ігноруючи це, оскільки немає жодного живого з'єднання, до якого ці пакети належать у брандмауері сервера.
Оскільки ви працюєте з Linux, уважно перевірте iptables
/ ip6tables
або ( nft
якщо ви використовуєте новий матеріал) на саме те, що ви дозволяєте, порівняно з випаданням. Дуже часто дозволити нові / встановлені / пов’язані пакети на порту TCP SSH, але не "недійсні" - якщо ви мовчки скидаєте все, що заборонено, ця звичайна установка може викликати подібні заморозки після коротких проблем з підключенням .
Сам ваш SSH-сервер може бути налаштований на закриття з'єднання після періоду бездіяльності, використовуючи один з параметрів OpenSSH для пакетів зберігання клієнтів TCP або SSH. Це само по собі не призведе до невизначеного зависання, але воно може поставити вас в один з описаних вище станів.
Можливо, ви просто не даєте йому достатньо часу, щоб самостійно "розчепитися" після того, як ви перейдете до стану, в якому засідає ssh
сеанс.
<Enter>
та введіть,~.
щоб сказати вашій стороні перервати з'єднання, і ви можете просто повторити останню команду ssh для повторного з'єднання (наприклад, зі стрілкою вгору чи!!
).