Сервис перезапускался при ошибке on failure

Иногда сервисы ни с того ни с сего падают и приходиться их вручную восстанавливать. Если для пользователя домашнего компьютера это не критично, потому что если сервис падает во время разработки, то это даже хорошо, можно сразу увидеть что есть проблема. Но на серверах и VPS сервисы должны работать постоянно для обеспечения доступа к веб-сайту или приложению.

В этой инструкции я покажу как настроить автоматический перезапуск сервиса Linux несколькими способами: с помощью скрипта мониторинга периодически запускаемого через cron и в systemd.

Автоматический перезапуск сервиса в systemd

По умолчанию, если ваш сервис будет убит или завершится некорректно, systemd не будет с ним ничего делать. Но можно настроить сервис так, чтобы при падении или даже остановке он автоматически перезапускался. Для этого используется директива Restart, которую надо добавить в секцию Service. Этот параметр может иметь такие значения:

  • on-failure — только если произошла ошибка;
  • on-success — только если процесс сервиса завершился без ошибок;
  • on-abnormal — только если сервис не отвечает;
  • always — перезапускать всегда, когда сервис был остановлен;

 Например, рассмотрим настройку автоматического перезапуска сервиса Apache:

sudo systemctl edit apache2

[Service]
Restart=on-failure
RestartSec=5s

Директива RestartSec указывает сколько ждать перед перезапуском сервиса. Когда завершите сохраните изменения и выполните команду daemon-reload, чтобы перечитать конфигурацию:

sudo systemctl daemon-reload

Затем чтобы проверить что всё работает посмотрите состояние процесса, завершите процесс сигналом kill:

sudo systemctl status apache2

kill -KILL 32091

И снова посмотрите состояние. Процесс будет запущен. Система инициализации автоматически перезапустит его как только он завершится с кодом возврата ошибки. Если вы хотите чтобы процесс перезапускался всегда, необходимо использовать директиву Restart: always. Однако с ней надо быть осторожным, она вовсе не даст вам завершить процесс, даже если будет необходимо. Для того, чтобы процесс, который постоянно падает не перезапускался, можно добавить лимит на количество перезапусков в секцию Service:

sudo systemctl edit apache2

[Service]
StartLimitIntervalSec=500
StartLimitBurst=5
Restart=on-failure
RestartSec=5s

Директивы StartLimitBurst и StartLimitIntervalSec указывают, что надо попытаться перезапустить сервис пять раз, и если он все эти пять раз упадёт, то больше его не трогать. Вторая директива ограничивает время перезапусков сервиса до 500 секунд.

Автоматический перезапуск сервиса с помощью скрипта

Это самый простой и самый надежный способ работающий абсолютно во всех дистрибутивах Linux и не требующий установки дополнительных утилит. Для того же Apache скрипт выглядит следующим образом:

sudo vi /usr/local/bin/apache-monitor.sh

#!/bin/bash
ps -A | grep apache2 || systemctl start apache2

Сохраните файл, сделайте его исполняемым:

chmod ugo+x /usr/local/bin/apache-monitor.sh

Теперь добавьте запись в cron для периодического запуска скрипта:

sudo crontab -e

*/5 * * * * /usr/local/bin/apache-monitor.sh

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

Решил вопрос: в итоге два юнита и bash лупер.
Первый юнит поднимает сервер от непривилегированного юзера:

[Unit]
Description=HTTrack web-server for 'vps'
After=network.target

[Service]
User=vps
Group=vps
Type=simple
ExecStart=/usr/lib/httrack/htsserver /usr/share/httrack/ --path /home/vps/httrack --language 8 --port 2340

[Install]
WantedBy=multi-user.target

Второй – контролёр первого:

[Unit]
Description=HTTrack bicycle
After=network.target

[Service]
Type=simple
ExecStart=/etc/httrack.sh
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

И луп (добивает, пока паучок не запустится с сокетом):

#!/bin/sh

while true
do
    if [ -z "$(netstat -tulpn | grep 2340)" ]
    then
        systemctl restart httrack-trans.service
    fi
    sleep 10
done

Не нравится, что на три файла разбросал. Триппер, конечно, но работает. Думаю, если бы HTTrack при траблах с соккетом завершался с каким-нибудь ненулевым кодом, то можно было реализовать ту же логику одним systemd.

Жалко, проект уже умирает. Так и не придумал, как по человечески закрыть вот эту дырку:

strace -f -e open ls 2>&1 | grep ^open
open("/usr/share/httrack/html/ping", O_RDONLY) = -1 ENOENT (No such file or directory)

А без интернета прям пичалька. Утешает то, что лор работает как часы – можно пользоваться напрямую, без предзагрузки.

Благодарю за обсуждение и советы.

rmu ★★

(09.11.19 18:05:56 MSK)

  • Показать ответ
  • Ссылка

На чтение 6 мин Опубликовано 07.08.2019

Существует множество причин сбоя / падения процесса в системе Linux, которые вы можете исследовать и устранить, но это может занять некоторое время.

Но одна вещь, которую вы можете сделать немедленно, чтобы перевести службу в оперативный режим, – это автоматический запуск, когда служба выходит из строя, что в конечном итоге сокращает время простоя и улучшает доступность.

Убедитесь, что ваш сервис всегда будет доступен для пользователей.

Это очень легко автоматизировать в системах systemd, поскольку в systemd есть опции, позволяющие это сделать.

Это также можно сделать с помощью bash-скрипта.

Что такое systemd?

Systemd – это новая система инициализации и менеджер системы, которая была внедрена / адаптирована во все основные дистрибутивы Linux поверх традиционных систем инициализации SysV.

systemd совместим со скриптами инициализации SysV и LSB.

Он может работать в качестве замены для системы sysvinit.

systemd – это первый процесс, запускаемый ядром и содержащий PID 1.

Это родительский процесс для всего, и Fedora 15 является первым дистрибутивом, который был адаптирован systemd вместо upstart.

systemctl – это утилита командной строки и основной инструмент для управления демонами / службами systemd, а именно (запуск, перезапуск, остановка, включение, отключение, перезагрузка и состояние).

systemd использует файлы .service вместо скриптов bash (используемых SysV init). systemd сортирует все демоны в свои собственные cgroups Linux, и вы можете увидеть иерархию системы, изучив файл /cgroup/systemd.

Сервисный файл systemd состоит из трех основных частей, и нам нужно добавить ниже обязательные параметры в разделе [Serivece]

[Unit]
...

[Service]
Restart=on-failure
RestartSec=5s
...

[Install]
...
  • Restart: определяет, будет ли служба перезапущена, когда процесс службы завершается, завершается или по истечении времени ожидания.
  • on-failure: если установлено значение on-failuire, служба будет перезапущена, когда процесс завершится с ненулевым кодом выхода, завершится с помощью сигнала, когда истечет время ожидания операции (например, перезагрузки службы), и когда настроен тайм-аут сторожевого таймера.
  • EstRestartSec: настраивает время ожидания перед перезапуском службы. Принимает значение без единиц измерения в секундах или значение промежутка времени, например «5min 20s». По умолчанию 100 ms.
  • S5s: он будет ждать 5 секунд, а затем запустить службу.

Как добавить параметр службы автоматического запуска в systemd System?

Нет ничего сложного в том, чтобы добавить эти параметры.

Для этого откройте соответствующий файл службы и добавьте следующие параметры.

Чтобы объяснить все это на примере, мы собираемся протестировать сервис httpd.

Давайте посмотрим его.

# vi /etc/systemd/system/multi-user.target.wants/httpd.service

[Unit]
Description=Apache Web Server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=simple
ExecStart=/usr/bin/httpd -k start -DFOREGROUND
ExecStop=/usr/bin/httpd -k graceful-stop
ExecReload=/usr/bin/httpd -k graceful
PrivateTmp=true
LimitNOFILE=infinity
KillMode=mixed
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target

Вам необходимо перезагрузить службу демона после внесения изменений.

Вы можете увидеть то же самое, запустив команду «systemctl status [httpd]», как показано ниже.

Кроме того, веб-сервер Apache httpd был запущен 27 минут назад.

# systemctl status httpd

● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2019-08-05 16:45:24 CDT; 27min ago
     Docs: man:httpd(8)
           man:apachectl(8)
  Process: 14420 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited, status=1/FAILURE)
Main PID: 14424 (httpd)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"
   CGroup: /system.slice/httpd.service
           ├─14424 /usr/sbin/httpd -DFOREGROUND
           ├─14425 /usr/sbin/httpd -DFOREGROUND
           ├─14426 /usr/sbin/httpd -DFOREGROUND
           ├─14427 /usr/sbin/httpd -DFOREGROUND
           ├─14428 /usr/sbin/httpd -DFOREGROUND
           └─14429 /usr/sbin/httpd -DFOREGROUND

Aug 05 16:45:23 thvtstrhl7 systemd[1]: Stopped The Apache HTTP Server.
Aug 05 16:45:23 thvtstrhl7 systemd[1]: Starting The Apache HTTP Server...
Aug 05 16:45:24 thvtstrhl7 systemd[1]: Started The Apache HTTP Server.
Warning: httpd.service changed on disk. Run 'systemctl daemon-reload' to reload units.




Просто перезапустите службу

# systemctl daemon-reload

Можно проверить, выполнив следующую команду еще раз.

# systemctl status httpd

● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2019-08-05 16:45:24 CDT; 27min ago
     Docs: man:httpd(8)
           man:apachectl(8)
Main PID: 14424 (httpd)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"
   CGroup: /system.slice/httpd.service
           ├─14424 /usr/sbin/httpd -DFOREGROUND
           ├─14425 /usr/sbin/httpd -DFOREGROUND
           ├─14426 /usr/sbin/httpd -DFOREGROUND
           ├─14427 /usr/sbin/httpd -DFOREGROUND
           ├─14428 /usr/sbin/httpd -DFOREGROUND
           └─14429 /usr/sbin/httpd -DFOREGROUND

Aug 05 16:45:23 thvtstrhl7 systemd[1]: Stopped The Apache HTTP Server.
Aug 05 16:45:23 thvtstrhl7 systemd[1]: Starting The Apache HTTP Server...
Aug 05 16:45:24 thvtstrhl7 systemd[1]: Started The Apache HTTP Server.

Чтобы поэкспериментировать с этим, используйте команду pidof, чтобы узнать PID процесса.

# pidof httpd

14429 14428 14427 14426 14425 14424

Как только вы получите информацию о PID, просто убейте их всех вместе, используя следующую команду.

# kill -9 14429 14428 14427 14426 14425 14424

После того, как вы убили PIDы httpd, просто выполните следующую команду, чтобы увидеть статус.

Система показывает, что служба выполняет автозапуск.

# systemctl status httpd

● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: activating (auto-restart) (Result: exit-code) since Mon 2019-08-05 17:14:26 CDT; 2s ago
     Docs: man:httpd(8)
           man:apachectl(8)
  Process: 15978 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited, status=1/FAILURE)
  Process: 14424 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=killed, signal=KILL)
Main PID: 14424 (code=killed, signal=KILL)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"

Aug 05 17:14:26 thvtstrhl7 systemd[1]: httpd.service: control process exited, code=exited status=1
Aug 05 17:14:26 thvtstrhl7 systemd[1]: Unit httpd.service entered failed state.
Aug 05 17:14:26 thvtstrhl7 systemd[1]: httpd.service failed.

Позвольте мне выполнить приведенную выше команду еще раз и посмотреть, как выглядят результаты.

Да, круто, все работает, как ожидалось.

Служба была запущена 564 миллисекунды назад.

# systemctl status httpd

● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2019-08-05 17:14:31 CDT; 564ms ago
     Docs: man:httpd(8)
           man:apachectl(8)
  Process: 15978 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited, status=1/FAILURE)
Main PID: 15987 (httpd)
   Status: "Processing requests..."
   CGroup: /system.slice/httpd.service
           ├─15987 /usr/sbin/httpd -DFOREGROUND
           ├─15988 /usr/sbin/httpd -DFOREGROUND
           ├─15989 /usr/sbin/httpd -DFOREGROUND
           ├─15990 /usr/sbin/httpd -DFOREGROUND
           ├─15991 /usr/sbin/httpd -DFOREGROUND
           └─15992 /usr/sbin/httpd -DFOREGROUND

Aug 05 17:14:31 thvtstrhl7 systemd[1]: Starting The Apache HTTP Server...
Aug 05 17:14:31 thvtstrhl7 systemd[1]: Started The Apache HTTP Server.

Пожалуйста, не спамьте и никого не оскорбляйте.

Это поле для комментариев, а не спамбокс.

Рекламные ссылки не индексируются!

Достаточно часто бывает необходимость не позволять сервисам падать «наглухо», а рестартовать их в случае аварийного завершения. Systemd позволяет это сделать достаточно просто.

Рассмотрим в качестве примера древний сервис php5-fpm:

systemctl status php5-fpm.service
● php5-fpm.service - The PHP FastCGI Process Manager
   Loaded: loaded (/lib/systemd/system/php5-fpm.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2021-06-30 10:14:55 MSK; 12h ago
  Process: 9349 ExecStartPre=/usr/lib/php5/php5-fpm-checkconf (code=exited, status=0/SUCCESS)
 Main PID: 9354 (php5-fpm)
   Status: "Processes active: 0, idle: 5, Requests: 499, slow: 0, Traffic: 0req/sec"
    Tasks: 6 (limit: 4700)
   Memory: 857.9M
   CGroup: /system.slice/php5-fpm.service
           ├─ 9354 php-fpm: master process (/etc/php5/fpm/php-fpm.conf)
           ├─ 9357 php-fpm: pool web19
           ├─ 9358 php-fpm: pool web19
           ├─ 9359 php-fpm: pool www
           ├─ 9360 php-fpm: pool www
           └─20671 php-fpm: pool www

Открываем на редактирование файл /lib/systemd/system/php5-fpm.service и видим обычное содержимое:

[Unit]
Description=The PHP FastCGI Process Manager
After=network.target

[Service] 
Type=notify
PIDFile=/var/run/php5-fpm.pid
ExecStartPre=/usr/lib/php5/php5-fpm-checkconf
ExecStart=/usr/sbin/php5-fpm --nodaemonize --fpm-config /etc/php5/fpm/php-fpm.conf
ExecReload=/bin/kill -USR2 $MAINPID

[Install]
WantedBy=multi-user.target

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

StartLimitIntervalSec=500
StartLimitBurst=5

А в секцию Service добавить:

Restart=on-failure
RestartSec=5s

После добавления нужно заставить systemd перечитать конфиги:

systemctl daemon-reload

И теперь, если сервис вдруг остановится по незапланированным причинам, в течение 5 секунд он будет перезапущен. Попыток рестарта сервиса будет 5 в течение 500 секунд и если все эти попытки закончатся неудачей, дальнейших попыток перезапуска не будет. Этого времени должно хватить сисадмину, чтобы среагировать на проблему вручную. 🙂

systemd version the issue has been seen with

253.1 / 252.6

Used distribution

Arch / Debian 12

Linux kernel version used

6.2.7-zen1-1-zen / 6.1.0-6-amd64

CPU architectures issue was seen on

x86_64

Component

systemd

Expected behaviour you didn’t see

OnSuccess dependencies are triggered after the unit completed successfully.

Unexpected behaviour you saw

OnSuccess dependencies are also triggered while the unit is restarting, when Restart=on-failure is set.

Steps to reproduce the problem

Use two dummy units

# /etc/systemd/system/myservice.service
[Unit]
OnSuccess=mysuccess.service
StartLimitBurst=2
StartLimitIntervalSec=1h


[Service]
Type=oneshot
ExecStart=/usr/bin/false
Restart=on-failure
# /etc/systemd/system/mysuccess.service
[Service]
Type=oneshot
ExecStart=/usr/bin/true

When starting myservice.service, this will also trigger mysuccess.service multiple times.

Additional program output to the terminal or log subsystem illustrating the issue

Mar 20 15:49:21 periculum systemd[1]: Starting myservice.service...
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Child 4446 belongs to myservice.service.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Main process exited, code=exited, status=1/FAILURE
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Failed with result 'exit-code'.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Service will restart (restart setting)
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Changed start -> failed
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Job 3357 myservice.service/start finished, result=failed
Mar 20 15:49:21 periculum systemd[1]: Failed to start myservice.service.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Unit entered failed state.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Consumed 1ms CPU time.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Changed failed -> auto-restart
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Service RestartSec=100ms expired, scheduling restart.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Trying to enqueue job myservice.service/restart/replace
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Installed new job myservice.service/restart as 3481
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Enqueued job myservice.service/restart as 3481
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Scheduled restart job, restart counter is at 1.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Changed auto-restart -> dead
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Job 3481 myservice.service/restart finished, result=done
Mar 20 15:49:21 periculum systemd[1]: Stopped myservice.service.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Converting job myservice.service/restart -> myservice.service/start
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Consumed 1ms CPU time.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Triggering OnSuccess= dependencies.
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Trying to enqueue job mysuccess.service/start/fail
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Installed new job mysuccess.service/start as 3605
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Enqueued job mysuccess.service/start as 3605
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Triggering OnSuccess= dependencies done (1 job).
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Will spawn child (service_enter_start): /usr/bin/false
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Passing 0 fds to service
Mar 20 15:49:21 periculum systemd[1]: myservice.service: About to execute /usr/bin/false
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Forked /usr/bin/false as 4448
Mar 20 15:49:21 periculum (false)[4448]: myservice.service: Executing: /usr/bin/false
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Changed dead -> start
Mar 20 15:49:21 periculum systemd[1]: Starting myservice.service...
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Will spawn child (service_enter_start): /usr/bin/true
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Passing 0 fds to service
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: About to execute /usr/bin/true
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Forked /usr/bin/true as 4449
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Changed dead -> start
Mar 20 15:49:21 periculum systemd[1]: Starting mysuccess.service...
Mar 20 15:49:21 periculum (true)[4449]: mysuccess.service: Executing: /usr/bin/true
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Child 4448 belongs to myservice.service.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Main process exited, code=exited, status=1/FAILURE
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Failed with result 'exit-code'.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Service will restart (restart setting)
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Changed start -> failed
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Job 3481 myservice.service/start finished, result=failed
Mar 20 15:49:21 periculum systemd[1]: Failed to start myservice.service.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Unit entered failed state.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Consumed 1ms CPU time.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Changed failed -> auto-restart
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Child 4449 belongs to mysuccess.service.
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Main process exited, code=exited, status=0/SUCCESS (success)
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Deactivated successfully.
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Service will not restart (restart setting)
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Changed start -> dead
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Job 3605 mysuccess.service/start finished, result=done
Mar 20 15:49:21 periculum systemd[1]: Finished mysuccess.service.
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Consumed 1ms CPU time.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Control group is empty.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Service RestartSec=100ms expired, scheduling restart.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Trying to enqueue job myservice.service/restart/replace
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Installed new job myservice.service/restart as 3729
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Enqueued job myservice.service/restart as 3729
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Scheduled restart job, restart counter is at 2.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Changed auto-restart -> dead
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Job 3729 myservice.service/restart finished, result=done
Mar 20 15:49:21 periculum systemd[1]: Stopped myservice.service.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Converting job myservice.service/restart -> myservice.service/start
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Consumed 1ms CPU time.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Triggering OnSuccess= dependencies.
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Trying to enqueue job mysuccess.service/start/fail
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Installed new job mysuccess.service/start as 3853
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Enqueued job mysuccess.service/start as 3853
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Triggering OnSuccess= dependencies done (1 job).
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Start request repeated too quickly.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Failed with result 'exit-code'.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Service restart not allowed.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Changed dead -> failed
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Job 3729 myservice.service/start finished, result=failed
Mar 20 15:49:21 periculum systemd[1]: Failed to start myservice.service.
Mar 20 15:49:21 periculum systemd[1]: myservice.service: Unit entered failed state.
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Will spawn child (service_enter_start): /usr/bin/true
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Passing 0 fds to service
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: About to execute /usr/bin/true
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Forked /usr/bin/true as 4450
Mar 20 15:49:21 periculum (true)[4450]: mysuccess.service: Executing: /usr/bin/true
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Changed dead -> start
Mar 20 15:49:21 periculum systemd[1]: Starting mysuccess.service...
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Child 4450 belongs to mysuccess.service.
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Main process exited, code=exited, status=0/SUCCESS (success)
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Deactivated successfully.
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Service will not restart (restart setting)
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Changed start -> dead
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Job 3853 mysuccess.service/start finished, result=done
Mar 20 15:49:21 periculum systemd[1]: Finished mysuccess.service.
Mar 20 15:49:21 periculum systemd[1]: mysuccess.service: Consumed 2ms CPU time.

С Новым Годом, Хабр!

Первого января все нормальные люди занимаются прокрастинацией, уничтожением стратегического запаса оливье и прочими, не связанными с физической или интеллектуальной нагрузкой вещами. Вот и я планировал присоединиться к этой новогодней армии, но не тут-то было!

Во всём виноват Хабр!

…. Точнее хабражители! А, если ещё точнее, всему виной — предновогодние статьи, в которых два никак не связанных между собой юзера изобрели два почти одинаковых велосипеда. Итак, встречайте моих сегодняшних героев!

Как создавался новогодний Хабрачат в этом году

Скачивается бинарник под нужную платформу из релизов на github. Можно положить его, например, в /usr/bin. Далее пишем простой скрипт, который будет перезапускать сервер, в случае падения.

… (пропущен башизм с бесконечным циклом и прочими sleep-ами)

​ оригинал

Безумный дом

В процессе эксплуатации я заметил, что Domoticz иногда падает с ошибкой. Чтобы поднимать его автоматически, напишу watchdog с помощью cron.

… (пропущены башизм, на пару с кронтабом)

Теперь каждые 5 минут будет запускаться скрипт, который проверит, работает ли Domoticz и перезапустит его, если это необходимо

​ оригинал

Что с этим делать и как дальше жить?

Я совершенно не планировал писать статью освещающую самые основы systemd, у меня в планах цикл статей из разряда «systemd для продолжающих», но жизнь, как видно, вносит свои коррективы, в результате пусть моя сегодняшняя, коротенькая статья будет своеобразным прологом к планируемуму циклу. Но так как про написание сервисных юнитов systemd написано 100500 хаутушек, то мы осветим только параметры относящиеся к автоматическому перезапуску сервисов, на конкретных примерах (и на затравку кое-что ещё ;-), в применении к статьям двух уважаемых хабровчан.

Делаем всё по фен-шую

Ну, я надеюсь, вы тут все достаточно технически грамотные, поэтому я сразу приведу готовые, самодокументированные юниты и конфиги, а также команды запуска всего этого безобразия.

«Как создавался Хабрачат в этом году»

Юнит(/etc/systemd/system/ssh-chat.service):

[Unit]
Description=SSH Chat Service
After=network.target network-online.target

[Service]
# Пользователь и группа, с правами которых будет запускаться сервис
User=ssh-chat
Group=ssh-chat
Type=simple
ExecStart=/usr/local/bin/ssh-chat --admin=/etc/ssh-chat/admins --bind=0.0.0.0:22 --log /var/log/ssh-chat.log --motd=/etc/ssh-chat/motd
# В каких случаях сервис будет автоматически перезагружаться.
# on-failure — в случае выхода с ненулевым кодом возврата.
Restart=on-failure
# Таймаут перед загрузкой сервиса, после падения.
RestartSec=1
# Capablities для сервиса. В данном случае - разрешение сервису
# биндиться на привилегированные порты (< 1000)
AmbientCapablities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multiuser.target

Конфиг для systemd-sysusers.service(/etc/sysusers.d/ssh-chat.conf):

u ssh-chat - "SSH Chat user" /etc/ssh-chat
# Поля записи:
# u : создаём пользователя
# ssh-chat : username
# - : или UID[:GID] в данном случае автоматически занять свободные UID/GID < 1000
# "SSH Chat user" : Описание, или "-", если не нужно.
# /etc/ssh-chat : Home Directory
# Может быть ещё одно поле -- login shell. По умолчанию /usr/bin/nologin

Инсталляция и запуск:

sudo systemctl restart systemd-sysusers.service && sudo systemctl enable --now ssh-chat

«Безумный дом»

Юнит(/etc/systemd/system/domoticz.service):

[Unit]
Description=Domoticz Daemon
After=network.target

[Service]
User=http
Group=http
# Эта директива позволяет выполнять подготовительные действия перед
# запуском сервиса. Модификатор "+" указывает выполнять их от рута.
ExecStartPre=+/usr/bin/install -d -m 0700 -o http -g http /var/run/domoticz
ExecStart=/opt/domoticz/domoticz -www 8080 -pidfile /var/run/domoticz/domoticz.pid
PIDFile=/var/run/domoticz/domoticz.pid
WorkingDirectory=/opt/domoticz
# Всё то же самое, что и в случае "хабрачата", только таймаут 5 секунд.
RestartSec=5
Restart=on-failure

[Install]
WantedBy=multi-user.target

Инсталляция и запуск:

sudo systemctl enable --now domoticz

Что дальше?

Возможности systemd, кратко освещённые в этой статье, а так-же многие другие, более подробно будут разобраны в следующих статьях цикла. Триггеры, поддержка бинарных форматов, «прозрачные»(transient) юниты, встроенная контейнеризация and more, more… Но нетерпеливые могут уже «вот прям щаз» заняться чтением одной из лучших документаций в мире линукс. Маны которые можно почитать по сегодняшней теме:

man systemd.unit
man systemd.service
man systemd.exec
man systemctl
man sysusers.d
man systemd-sysusers

И на закуску маленький секрет. Один из моих любимых манов: man systemd.directives — путеводитель по всем директивам конфигурации которые могут встретиться вам в процессе изучения systemd.

Ещё раз С новым Годом, Хабр! И используйте правильные инструменты!

PS: Добавил ссылку на ман по systemd.exec. Как-то я про него малость забыл.

PPS: Добавил ссылки на ресурсы.

Список статей серии

  1. Почему хабражители предпочитают велосипеды, вместо готовых решений? Или о systemd, part 0

  2. Systemd для продолжающих. Part 1 — Запуск юнитов по временным событиям

  3. Systemd для продолжающих. Part 2 — Триггеры на различные события

Ресурсы

  • systemd.io — Статьи по внутренней кухне systemd. Частенько упоминается в манах.

  • systemd @ freedesktop.org — Основная страница с манами, документацией, видео, блогами и прочими ссылками на ресурсы.

  • @ru_systemd — Русскоязычный чат в Telegram. У нас тепло и лампово.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Продолжать?

Проголосовали 662 пользователя.

Воздержались 58 пользователей.

There are many reasons for systemd crash/go down on Linux, which you can investigate and fix ,but it is time consuming.

One thing you can do it immediately to bring the service back to online is  auto start when it goes down, which eventually reduce the downtime for better availability and to make sure that your service will be always available for users access.

It’s very easy to automate this on systemd systems because it has an options to enable this.

It can be done by bash script. We already had developed a bash script to automatically start a services when it’s crash on Linux.

What is systemd?

Systemd is a new init system and system manager which was implemented/adapted into all the major Linux distributions over the traditional SysV init systems.

systemd is compatible with SysV and LSB init scripts. It can work as a drop-in replacement for sysvinit system.

systemd is the first process which will  get started by kernel and holding PID 1.

It’s a parent process for everything and Fedora 15 is the first distribution which was adapted systemd instead of upstart.

systemctl is a command line utility and primary tool to manage the systemd daemons/services such as (start, restart, stop, enable, disable, reload & status).

systemd uses .service files Instead of bash scripts (SysV init uses). systemd sorts all daemons into their own Linux cgroups and you can see the system hierarchy by exploring /cgroup/systemd file.

The systemd service file has three major parts and we need to add the below required parameters under [Service] potion.

[Unit]
...

[Service]
Restart=on-failure
RestartSec=5s
...

[Install]
...
  • Restart: Configures whether the service shall be restarted when the service process exits, is killed, or a timeout is reached.
  • on-failure: If set to on-failure, the service will be restarted when the process exits with a non-zero exit code, is terminated by a signal, when an operation (such as service reload) times out, and when the configured watchdog timeout is triggered.
  • RestartSec: Configures the time to sleep before restarting a service. Takes a unit-less value in seconds, or a time span value such as “5min 20s”. Defaults to 100ms.
  • 5s: It will wait for 5 sec then start the service.

How to add Auto Start service parameter in systemd System?

It’s not a big deal to add these parameters. Open the corresponding service file and append the following parameters.

To explain this, we are going to test httpd service. Let’s see this.

# vi /etc/systemd/system/multi-user.target.wants/httpd.service

[Unit]
Description=Apache Web Server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=simple
ExecStart=/usr/bin/httpd -k start -DFOREGROUND
ExecStop=/usr/bin/httpd -k graceful-stop
ExecReload=/usr/bin/httpd -k graceful
PrivateTmp=true
LimitNOFILE=infinity
KillMode=mixed
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target

You need to reload the daemon service once you made the changes. You can see the same by running the “systemctl status [httpd]” command as shown below.

We could see that, it is marked in color for better visibility. Also, the Apache httpd web server was started 27 mins ago.

# systemctl status httpd

● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2019-08-05 16:45:24 CDT; 27min ago
     Docs: man:httpd(8)
           man:apachectl(8)
  Process: 14420 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited, status=1/FAILURE)
Main PID: 14424 (httpd)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"
   CGroup: /system.slice/httpd.service
           ├─14424 /usr/sbin/httpd -DFOREGROUND
           ├─14425 /usr/sbin/httpd -DFOREGROUND
           ├─14426 /usr/sbin/httpd -DFOREGROUND
           ├─14427 /usr/sbin/httpd -DFOREGROUND
           ├─14428 /usr/sbin/httpd -DFOREGROUND
           └─14429 /usr/sbin/httpd -DFOREGROUND

Aug 05 16:45:23 thvtstrhl7 systemd[1]: Stopped The Apache HTTP Server.
Aug 05 16:45:23 thvtstrhl7 systemd[1]: Starting The Apache HTTP Server...
Aug 05 16:45:24 thvtstrhl7 systemd[1]: Started The Apache HTTP Server.
Warning: httpd.service changed on disk. Run 'systemctl daemon-reload' to reload units.

Just reload the daemon service.

# systemctl daemon-reload

This will go off now. It can be verified by running the following command once again.

# systemctl status httpd

● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2019-08-05 16:45:24 CDT; 27min ago
     Docs: man:httpd(8)
           man:apachectl(8)
Main PID: 14424 (httpd)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"
   CGroup: /system.slice/httpd.service
           ├─14424 /usr/sbin/httpd -DFOREGROUND
           ├─14425 /usr/sbin/httpd -DFOREGROUND
           ├─14426 /usr/sbin/httpd -DFOREGROUND
           ├─14427 /usr/sbin/httpd -DFOREGROUND
           ├─14428 /usr/sbin/httpd -DFOREGROUND
           └─14429 /usr/sbin/httpd -DFOREGROUND

Aug 05 16:45:23 thvtstrhl7 systemd[1]: Stopped The Apache HTTP Server.
Aug 05 16:45:23 thvtstrhl7 systemd[1]: Starting The Apache HTTP Server...
Aug 05 16:45:24 thvtstrhl7 systemd[1]: Started The Apache HTTP Server.

To experiment this, use pidof command to find out the PID of a process. We can find out the process id (PID) in Linux using nine ways.

# pidof httpd

14429 14428 14427 14426 14425 14424

Once you get the PID details, just kill them all together in one go using the following command. There are many similar commands are available in Linux to Kill a Process ID (PID).

# kill -9 14429 14428 14427 14426 14425 14424

Once you killed the httpd PID, just run the following command to see the status. It’s showing the service is getting auto-restart. But still it’s not up.

# systemctl status httpd

● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: activating (auto-restart) (Result: exit-code) since Mon 2019-08-05 17:14:26 CDT; 2s ago
     Docs: man:httpd(8)
           man:apachectl(8)
  Process: 15978 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited, status=1/FAILURE)
  Process: 14424 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=killed, signal=KILL)
Main PID: 14424 (code=killed, signal=KILL)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"

Aug 05 17:14:26 thvtstrhl7 systemd[1]: httpd.service: control process exited, code=exited status=1
Aug 05 17:14:26 thvtstrhl7 systemd[1]: Unit httpd.service entered failed state.
Aug 05 17:14:26 thvtstrhl7 systemd[1]: httpd.service failed.

Let me run the above command once again and see how the results looks. Yup, awesome, it’s running now. it’s working as expected.

It was started 564 Millisecond sec ago.

# systemctl status httpd

● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2019-08-05 17:14:31 CDT; 564ms ago
     Docs: man:httpd(8)
           man:apachectl(8)
  Process: 15978 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited, status=1/FAILURE)
Main PID: 15987 (httpd)
   Status: "Processing requests..."
   CGroup: /system.slice/httpd.service
           ├─15987 /usr/sbin/httpd -DFOREGROUND
           ├─15988 /usr/sbin/httpd -DFOREGROUND
           ├─15989 /usr/sbin/httpd -DFOREGROUND
           ├─15990 /usr/sbin/httpd -DFOREGROUND
           ├─15991 /usr/sbin/httpd -DFOREGROUND
           └─15992 /usr/sbin/httpd -DFOREGROUND

Aug 05 17:14:31 thvtstrhl7 systemd[1]: Starting The Apache HTTP Server...
Aug 05 17:14:31 thvtstrhl7 systemd[1]: Started The Apache HTTP Server.

It can be done for any services as required. I hope this article helps you.

Systemd allows you to configure a service so that it automatically restarts in case it’s crashed.

Take a typical unit file that looks like this.

$ cat /etc/systemd/system/yourdaemon.service
[Unit]
Description=Your Daemon
After=network-online.target
Wants=network-online.target systemd-networkd-wait-online.service

[Service]
ExecStart=/path/to/daemon

[Install]
WantedBy=multi-user.target

Most unit files are longer, but this gives you the gist of it. In the above example, if your daemon would crash or be killed, systemd would leave it alone.

You can however let systemd auto-restart it in case it fails or is accidentally killed. To do so, you can add the Restart option to the [Service] stanza.

$ cat /etc/systemd/system/yourdaemon.service
[Unit]
Description=Your Daemon
After=network-online.target
Wants=network-online.target systemd-networkd-wait-online.service

StartLimitIntervalSec=500
StartLimitBurst=5

[Service]
Restart=on-failure
RestartSec=5s

ExecStart=/path/to/daemon

[Install]
WantedBy=multi-user.target

The above will react to anything that stops your daemon: a code exception, someone that does kill -9 <pid>, … as soon as your daemon stops, systemd will restart it in 5 seconds.

In this example, there are also StartLimitIntervalSec and StartLimitBurst directives in the [Unit] section. This prevents a failing service from being restarted every 5 seconds. This will give it 5 attempts, if it still fails, systemd will stop trying to start the service.

(Note: if you change your systemd unit file, make sure to run systemctl daemon-reload to reload the changes.)

If you ask for the status of your daemon after it’s been killed, systemd will show activating (auto-restart).

$ systemctl status yourdaemon
● yourdaemon.service - Your Daemon
   Loaded: loaded (/etc/systemd/system/yourdaemon.service; enabled; vendor preset: enabled)
   Active: activating (auto-restart) (Result: signal) since Mon 2020-01-13 09:07:41 UTC; 4s ago
  Process: 27165 ExecStart=/path/to/daemon (code=killed)
  Main PID: 27165 (code=killed, signal=KILL)

Give it a few seconds, and you’ll see the daemon was automatically restarted by systemd.

$ systemctl status yourdaemon
● yourdaemon.service - Your Daemon
   Loaded: loaded (/etc/systemd/system/yourdaemon.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2020-01-13 09:07:46 UTC; 6min ago

Pretty useful if you have a buggy service that’s safe to just restart on failure!

Достаточно часто бывает необходимость не позволять сервисам падать «наглухо», а рестартовать их в случае аварийного завершения. Systemd позволяет это сделать достаточно просто.

Рассмотрим в качестве примера древний сервис php5-fpm:

systemctl status php5-fpm.service
● php5-fpm.service - The PHP FastCGI Process Manager
   Loaded: loaded (/lib/systemd/system/php5-fpm.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2021-06-30 10:14:55 MSK; 12h ago
  Process: 9349 ExecStartPre=/usr/lib/php5/php5-fpm-checkconf (code=exited, status=0/SUCCESS)
 Main PID: 9354 (php5-fpm)
   Status: "Processes active: 0, idle: 5, Requests: 499, slow: 0, Traffic: 0req/sec"
    Tasks: 6 (limit: 4700)
   Memory: 857.9M
   CGroup: /system.slice/php5-fpm.service
           ├─ 9354 php-fpm: master process (/etc/php5/fpm/php-fpm.conf)
           ├─ 9357 php-fpm: pool web19
           ├─ 9358 php-fpm: pool web19
           ├─ 9359 php-fpm: pool www
           ├─ 9360 php-fpm: pool www
           └─20671 php-fpm: pool www

Открываем на редактирование файл /lib/systemd/system/php5-fpm.service и видим обычное содержимое:

[Unit]
Description=The PHP FastCGI Process Manager
After=network.target

[Service] 
Type=notify
PIDFile=/var/run/php5-fpm.pid
ExecStartPre=/usr/lib/php5/php5-fpm-checkconf
ExecStart=/usr/sbin/php5-fpm --nodaemonize --fpm-config /etc/php5/fpm/php-fpm.conf
ExecReload=/bin/kill -USR2 $MAINPID

[Install]
WantedBy=multi-user.target

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

StartLimitIntervalSec=500
StartLimitBurst=5

А в секцию Service добавить:

Restart=on-failure
RestartSec=5s

После добавления нужно заставить systemd перечитать конфиги:

systemctl daemon-reload

И теперь, если сервис вдруг остановится по незапланированным причинам, в течение 5 секунд он будет перезапущен. Попыток рестарта сервиса будет 5 в течение 500 секунд и если все эти попытки закончатся неудачей, дальнейших попыток перезапуска не будет. Этого времени должно хватить сисадмину, чтобы среагировать на проблему вручную. 🙂

Понравилась статья? Поделить с друзьями:
  • Сервис парктроник opel astra ошибка
  • Серебряный работа над ошибками
  • Сервис исправления орфографических ошибок
  • Сериал врачебная ошибка 2020 содержание
  • Сериал врачебная ошибка 2020 скачать торрент