отказ
Если ваше 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 еще больше символов (конечно, без ответа), а затем снова подключился к моему WiFi - переподключение действительно не удалось хотя бы один раз из-за плохого сигнала и других факторов затем снова подключился: я подождал около пяти секунд для восстановления 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-порту TCP SSH, но не «недействительные» - если вы молча отбрасываете все, что не разрешено, эта общая установка может вызвать такие зависания после кратких проблем с подключением ,
Ваш SSH-сервер может быть настроен на закрытие соединения после определенного периода бездействия, используя один из параметров OpenSSH для пакетов поддержки активности клиента TCP или SSH. Само по себе это не вызовет неопределенных зависаний, но может поставить вас в одно из состояний, описанных выше.
Возможно, вы просто не даете ему достаточно времени, чтобы «развязать» его самостоятельно, после того как вы попали в состояние, в котором ваш ssh
сеанс зависает.
<Enter>
и напечатайте,~.
чтобы сообщить своей стороне, что нужно разорвать соединение, и вы можете просто повторить последнюю команду ssh для повторного соединения (например, с помощью стрелки вверх или!!
).