Привет, Хабр! Представим ситуацию: вы настраиваете сервер, работаете с критически важными процессами или изучаете логи - и внезапно SSH-соединение обрывается. Все не сохранённые изменения улетучиваются, прогресс откатывается, а вам приходится переподключаться и начинать всё заново.
В данной статье представлен скрипт-реаниматор для SSH, который:
Восстанавливает соединение при любых обрывах
Сохраняет рабочую сессию и историю команд
Поддерживает tmux/screen для полного сохранения контекста
Может отправлять уведомления о проблемах в Telegram
Решение представлено для Bash и PowerShell
Введение
SSH-реаниматор фактически является "обёрткой" вокруг SSH-клиента, которая:
Постоянно мониторит соединение
При обрыве делает паузу, пытается перезагрузиться и восстанавливает предыдущее окружение
Логирует все события, если потребуется анализ
Например: вы запускаете бэкап на 3 часа. Без реаниматора в случае обрыва Вам придётся начинать заново, но не в стиуации с реаниматором. Он восстановит создание бэкапа с прогрессом, на котором произошёл обрыв.
Важное уточнение: скрипт не является заменой полноценного решения в стиле Zabbix, Nagios и тд. Он лишь даёт простой и быстрый способ сделать рутинные подключения устойчивыми к сбоям. Может помочь, к примеру, в ситуации с какой-нибудь простенькой VPS, где Zabbix (и прочие) являются чересчур избыточными решениями.
Принцип работы SSH-реаниматора
1. Детектирование обрыва соединения
SSH использует 2 ключевых параметра для мониторинга активности соединения:
ServerAliveInterval
(по умолчанию значение "0" - отключено)
Определяет интервал в секундах между keepalive-пакетами
Со стороны клиента отправляются пакеты для проверки активности сервера
ServerAliveCountMax
(по умолчанию значение "3")
Кол-во неудачных попыток проверки перед разрывом
Умножается на
ServerAliveInterval
для получения общего таймаута
Посмотрим подробнее пример расчёта:
ssh -o ServerAliveInterval=20 -o ServerAliveCountMax=4 user@host
20 x 4 = 80 секунд без ответа
2. Механизм бесконечного переподключения
Скрипт, который будет описан ниже, использует цикл while true
для постоянного поддержания соединения:
while true; do
ssh -o ServerAliveInterval=30 user@host
if [ $? -eq 0 ]; then
break # Корректный выход
else
sleep 5 # Пауза перед повторной попыткой
fi
done
Ключевые моменты:
Проверка кода возврата SSH (0 - успех, иные - ошибка)
Задержка между попытками для избежания цикла быстрых переподключений
Bash-скрипт
#!/bin/bash
SERVER="user@example.com"
SSH_OPTS="-o ServerAliveInterval=30 -o ServerAliveCountMax=3"
DELAY=5
while true; do
echo "[$(date +'%H:%M:%S')] Подключение к $SERVER..."
ssh $SSH_OPTS $SERVER
if [ $? -eq 0 ]; then
echo "[$(date +'%H:%M:%S')] Сессия завершена"
break
else
echo "[$(date +'%H:%M:%S')] Ошибка соединения. Повтор через $DELAY сек..."
sleep $DELAY
fi
done
Bash-скрипт с восстановлением tmux
#!/bin/bash
SERVER="user@example.com"
SESSION="remote_work"
SSH_OPTS="-o ServerAliveInterval=30 -o ServerAliveCountMax=3"
while true; do
echo "[$(date +'%H:%M:%S')] Подключение к сессии $SESSION на $SERVER..."
ssh -t $SSH_OPTS $SERVER "tmux attach -t $SESSION || tmux new -s $SESSION"
if [ $? -eq 0 ]; then
break
else
sleep 5
fi
done
PowerShell-скрипт
$SERVER = "user@example.com"
$SSH_OPTS = "-o ServerAliveInterval=30 -o ServerAliveCountMax=3"
$DELAY = 5
while ($true) {
Write-Host "[$(Get-Date -Format 'HH:mm:ss')] Подключение к $SERVER..."
ssh $SSH_OPTS $SERVER
if ($LASTEXITCODE -eq 0) {
break
} else {
Start-Sleep -Seconds $DELAY
}
}
Как использовать
-
Сохранить скрипт:
nano ssh_reconnect.sh chmod +x ssh_reconnect.sh
-
Запустить с логированием:
./ssh_reconnect.sh >> ssh_log.txt 2>&1
-
Запустить в фоновом режиме:
nohup ./ssh_reconnect.sh > /dev/null 2>&1 &
Также, ещё пара полезных функций:
Telegram-уведомления:
TELEGRAM_API="https://api.telegram.org/bot{TOKEN}/sendMessage"
CHAT_ID="12345"
MESSAGE="Ошибка SSH соединения с $SERVER"
curl -s -X POST $TELEGRAM_API -d chat_id=$CHAT_ID -d text="$MESSAGE"
-
Автозапуск через crontab:
@reboot /path/to/ssh_reconnect.sh
-
Сохранение истории команд:
ssh $SERVER "cat >> ~/.persistent_history"
Рекомендации
Для критически важных сессий используйте tmux или screen
Настройте оптимальные значения ServerAliveInterval для вашего соединения
Для долгоживущих сессий рассмотрите возможность использования terminal multiplexers
Включите логирование для анализа причин разрывов
Заключение
Представленные в статье скрипты помогут обеспечить надёжное поддержание SSH-соединения, восстановить сессию после обрывов и сохранить рабочее окружение. Решение можно допиливать и адаптировать под различные требования, расширять функционал.
P.S. Я веду свою группу в Телеграмм, буду рад видеть всех, кому интересен процесс написания скриптов и автоматизация в мире IT.
Комментарии (14)
Nill-Ringil
15.07.2025 13:39amurchick
15.07.2025 13:39Ага, я с mosh уже лет 10 как забыл, что такое обрывы сессий.
Nill-Ringil
15.07.2025 13:39Долго его использовал, последние пару лет как-то ушел от него, но решил, что он тут просто один вместо всей статьи может быть
Johan_Palych
15.07.2025 13:39Посылать сигнал я-живой через 30 сек:
ssh -o ServerAliveInterval=30 user@some.host.com
Или так:На сервере в sshd_config: ClientAliveCountMax 99999 ClientAliveInterval 30 На клиенте в ~/.ssh/config или глобально в ssh_config: ServerAliveInterval 30 ServerAliveCountMax 99999
CaptainFlint
15.07.2025 13:39Не уловил, где он "восстанавливает предыдущее окружение". Я уж не говорю про "восстановит создание бэкапа". Рестартануть SSH я и сам могу, "вверх-Enter". Главная беда обычно в том, что запущенная в SSH-сессии интерактивная программа к этому моменту уже рухнула по SIGHUP, значения всяких переменных потерялись, текущий путь забылся, вся история команд сдохла. Рестарт SSH ничего этого не вернёт.
Я себе для таких задач EternalTerminal поднимаю, он удерживает контекст практически всегда. Но, к сожалению, он должен устанавливаться в том числе и на сервер, что не всегда возможно.
jackgrebe
15.07.2025 13:39% apt info autossh
Package: autossh
Version: 1.4g-1+b1
Priority: optional
Section: net
Source: autossh (1.4g-1)
Maintainer: Axel Beckert abe@debian.org
Installed-Size: 94.2 kB
Depends: openssh-client | ssh-client, libc6 (>= 2.14)
Enhances: openssh-client, ssh-client
Homepage: https://www.harding.motd.ca/autossh/
Tag: implemented-in::c, interface::daemon, network::hiavailability,
network::server, protocol::ssh, role::program, use::login, use::monitor
Download-Size: 35.4 kB
Description: Automatically restart SSH sessions and tunnels
autossh is a program to start an instance of ssh and monitor it, restarting it
as necessary should it die or stop passing traffic. The idea is from rstunnel
(Reliable SSH Tunnel), but implemented in C. Connection monitoring is done
using a loop of port forwardings. It backs off on the rate of connection
attempts when experiencing rapid failures such as connection refused.
grucshetsky_aleksei
15.07.2025 13:39mosh, screen, tmux. Для кого вообще эти утилиты написаны были? Нет, надо скриптами извращаться
CaptainFlint
15.07.2025 13:39Вот лично я, скажем, так и не смог всеми этими утилитами пользоваться. Во всяком случае, не в качестве постоянной замены SSH. Очень уж они неудобны и ограничены, ломают интеграцию с графическими терминалами.
adsha
15.07.2025 13:39Что мешает в графическом терминале тупо запустить
tmux
? Это и отвязка от зависимости качества соединения с инициатором при копировании, и сохранение контекста сессии. При обрыве достаточно `tmux a -t0` при условии, что сессия поднималась тупо командойtmux
ferosod
А разве заббикс позволяет каким либо образом сохранять контекст после обрыва ssh? Это же система мониторинга просто