MAATRIX / Блог / Настройка автоматического перезапуска упавших сервисов

Настройка автоматического перезапуска упавших сервисов

Настройка автоматического перезапуска упавших сервисов

MAATRIX

Сервис упал ночью, а сайт лежал до утра, пока вы не проснулись и не перезапустили его руками — знакомая ситуация. В нормальной эксплуатации сервера такого быть не должно: упавший процесс обязан подниматься сам за секунды. Ниже разберём, как настроить автоматический перезапуск сервисов через systemd, добавить проверку здоровья и защититься от бесконечного цикла падений — с готовыми командами и конфигами.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Почему сервисы падают и зачем автоперезапуск

Любой сервис может завершиться неожиданно: из-за нехватки памяти и работы OOM-killer, необработанного исключения в коде, кратковременной недоступности базы данных, бага после обновления. Это нормально — важно не то, что процесс упал, а то, как быстро он вернётся. Ручной перезапуск означает простой длиной от минут до часов, пока вы заметите проблему. Автоматический возвращает сервис за секунды, и большинство сбоев проходит незамеченными для пользователей.

Правильный подход — не писать самодельные скрипты в кроне, которые проверяют процесс и запускают его, а использовать штатный механизм systemd. Он есть в любой современной Ubuntu и Debian, умеет следить за процессом, перезапускать его по заданным правилам, вести журнал и не допускать бесконечного цикла рестартов. Это надёжнее и прозрачнее самописных костылей.

Базовая настройка автоперезапуска в systemd

Если ваш сервис уже оформлен как systemd-юнит, добавить автоперезапуск — вопрос двух строк. Откройте юнит, например /etc/systemd/system/myapp.service, и в секцию [Service] добавьте политику перезапуска:

[Service]
Restart=always
RestartSec=3

Директива Restart=always перезапускает сервис при любом завершении, а RestartSec=3 задаёт паузу в три секунды перед попыткой, чтобы не молотить рестартами вплотную. После правки перечитайте конфигурацию и перезапустите юнит:

systemctl daemon-reload
systemctl restart myapp
systemctl status myapp

Есть несколько вариантов политики. Restart=on-failure перезапускает только при аварийном завершении с ненулевым кодом, но не трогает штатную остановку — это разумный выбор для большинства приложений. Restart=always возвращает сервис даже после нормального выхода, что полезно для демонов, которые всегда должны работать. Выбирайте по смыслу: для веб-приложения обычно подходит on-failure, для фонового воркера — always.

Стоит понимать, почему systemd лучше самодельных решений, которые часто пишут новички. Классический костыль — скрипт в кроне, который раз в минуту проверяет, жив ли процесс, и запускает его заново. У такого подхода куча слабых мест: минимальная реакция раз в минуту вместо секунд, риск запустить второй экземпляр поверх подвисшего первого, отсутствие внятного журнала и лимита на частоту рестартов. systemd лишён всех этих проблем: он владеет процессом напрямую, видит момент его завершения мгновенно, гарантирует единственный экземпляр, ведёт полный журнал причин падений и умеет останавливаться при цикле сбоев. Поэтому, если сервис можно оформить как systemd-юнит, это почти всегда правильнее, чем изобретать свою систему присмотра. Исключение — контейнеры, где ту же роль выполняет политика перезапуска самого Docker или оркестратора, и отдельный присмотр со стороны хоста не нужен.

Отдельно продумайте порядок зависимостей. Если ваш сервис не может работать без базы данных или другой службы, укажите это в юните через директивы After и Requires. Тогда systemd будет поднимать сервис только после готовности его зависимостей и корректно перезапускать связку целиком. Без этого приложение может стартовать раньше базы, падать при первой же попытке подключения и уходить в цикл рестартов на пустом месте — а виноват окажется не код, а неправильно описанный порядок запуска.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Защита от бесконечного цикла рестартов

У автоперезапуска есть коварная ловушка: если сервис падает сразу после старта из-за сломанного конфига или отсутствующей базы, systemd будет перезапускать его снова и снова, нагружая сервер вхолостую. Чтобы этого не случилось, ограничьте частоту рестартов. В секции [Unit] задайте окно и лимит попыток:

[Unit]
StartLimitIntervalSec=60
StartLimitBurst=5

Такая настройка означает: если сервис упал пять раз за минуту, systemd прекращает попытки и оставляет его в состоянии failed, вместо того чтобы бесконечно долбить старт. Это правильное поведение — постоянное падение говорит о реальной проблеме, которую нужно чинить руками, а не маскировать рестартами. О том, что сервис ушёл в failed, вы узнаете из мониторинга и сможете разобраться спокойно.

Перезапуск по проверке здоровья

Иногда процесс формально жив, но не работает: веб-сервер висит и не отвечает на запросы, приложение зациклилось, соединение с базой зависло. systemd видит живой процесс и не вмешивается, а пользователи получают ошибки. Для таких случаев нужен healthcheck — проверка не факта существования процесса, а его реальной работоспособности.

Простейший вариант — отдельный таймер systemd, который раз в минуту дёргает служебный URL приложения и перезапускает сервис, если ответа нет. Скрипт проверки выглядит так:

curl -fs http://localhost:8080/health || systemctl restart myapp

Этот однострочник запрашивает эндпоинт здоровья и, если тот не ответил успешно, перезапускает сервис. Оформите его как systemd-таймер или добавьте в юнит директиву WatchdogSec, если приложение умеет слать сигналы готовности. Для контейнеров аналогичную роль играет healthcheck в Docker и политика перезапуска restart: unless-stopped. Смысл везде один: проверять не жизнь процесса, а его способность отвечать.

Не забудьте про причину падений

Автоперезапуск лечит симптом, а не болезнь. Если сервис падает регулярно, важно найти и устранить корень, иначе вы просто маскируете проблему. После настройки рестартов загляните в журнал и посмотрите, почему сервис завершался:

journalctl -u myapp --since "1 hour ago" --no-pager

Частые причины стоит устранять целенаправленно. Если виноват OOM-killer — не хватает памяти, и нужно либо оптимизировать приложение, либо добавить RAM. Если падения совпадают с пиками нагрузки — сервер перерос тариф. Если сервис валится после деплоя — проблема в новом коде или конфиге. Автоперезапуск даёт вам время разобраться без паники, но не заменяет починку. Если корень — нехватка ресурсов, честнее повысить тариф: масштабировать VPS у MAATRIX можно без переезда, добавив память и ядра, с оплатой из России картой или криптой.

Проверка и профилактика

После настройки обязательно проверьте, что механизм работает. Убейте процесс вручную командой kill и убедитесь, что systemd поднял его за заданные секунды, а systemctl status показывает свежий аптайм. Проверьте и поведение после перезагрузки сервера: юнит должен быть в автозапуске через systemctl enable. Хорошая практика эксплуатации сервера — держать список критичных сервисов с настроенным автоперезапуском и раз в пару недель прогонять по нему проверку. Так вы будете уверены, что при ночном сбое сайт поднимется сам, а вы узнаете об инциденте из уведомления, а не из гневных сообщений пользователей.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Частые вопросы

Какую политику перезапуска выбрать?

Для веб-приложений обычно Restart=on-failure — он реагирует на аварии, но не мешает штатной остановке. Для фоновых демонов, которые всегда должны работать, подходит Restart=always.

Как избежать бесконечных рестартов?

Задайте StartLimitIntervalSec и StartLimitBurst: после нескольких падений подряд systemd остановит попытки и оставит сервис в failed, чтобы вы починили причину.

Что делать, если процесс жив, но не отвечает?

Настроить healthcheck: таймер, который проверяет служебный URL и перезапускает сервис при отсутствии ответа, либо watchdog в самом приложении.

Автоперезапуск решает проблему падений?

Нет, он лечит симптом. Причину — нехватку памяти, баги, нагрузку — нужно устранять отдельно, а рестарт лишь даёт время разобраться без простоя.

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.