На чтение 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.
Пожалуйста, не спамьте и никого не оскорбляйте.
Это поле для комментариев, а не спамбокс.
Рекламные ссылки не индексируются!
Иногда сервисы ни с того ни с сего падают и приходиться их вручную восстанавливать. Если для пользователя домашнего компьютера это не критично, потому что если сервис падает во время разработки, то это даже хорошо, можно сразу увидеть что есть проблема. Но на серверах и 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
На этом все, автоматический перезапуск сервисов штука может и немного сложная, но необходимая в серьезных системах.

Статья распространяется под лицензией Creative Commons ShareAlike 4.0 при копировании материала ссылка на источник обязательна .
Об авторе
![]()
Основатель и администратор сайта losst.ru, увлекаюсь открытым программным обеспечением и операционной системой Linux. В качестве основной ОС сейчас использую Ubuntu. Кроме Linux, интересуюсь всем, что связано с информационными технологиями и современной наукой.
The systemd.service man page has a description of the values Restart= takes, and a table of what options cause a restart when. Always pretty much does what it says on the lid:
If set to
always, the service will be restarted regardless of whether it exited cleanly or not, got terminated abnormally by a signal, or hit a timeout.
I don’t know for sure what situation they had in mind for that feature, but we might hypothesise e.g. a service configured to only run for a fixed period of time or to serve fixed number of requests and to then stop to avoid any possible resource leaks. Having systemd do the restarting makes for a cleaner implementation of the service itself.
In some sense, we might also ask why not include that option in systemd. Since it is capable of restarting services on failure, they might as well include the option of restarting the service always, just in case someone needs it. To provide tools, not policy.
Note also that a «successful exit» here is defined rather broadly:
If set to
on-success, it will be restarted only when the service process exits cleanly. In this context, a clean exit means an exit code of 0, or one of the signalsSIGHUP,SIGINT,SIGTERMorSIGPIPE, […]
SIGHUP is a common way of asking a process to restart, but it unhandled, it
terminates the process. So having Restart=always (or Restart=on-success) allows to use SIGHUP for restarting, even without the service itself supporting that.
Also, as far as I can read the man page, always doesn’t mean it would override the limits set by StartLimitInterval and StartLimitBurst:
Note that service restart is subject to unit start rate limiting configured with
StartLimitIntervalSec=andStartLimitBurst=, see systemd.unit(5) for details. A restarted service enters the failed state only after the start limits are reached.
Достаточно часто бывает необходимость не позволять сервисам падать «наглухо», а рестартовать их в случае аварийного завершения. 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 секунд и если все эти попытки закончатся неудачей, дальнейших попыток перезапуска не будет. Этого времени должно хватить сисадмину, чтобы среагировать на проблему вручную. 🙂
Yes, you can use Restart=on-failure inside the unit’s Service section.
From systemd’s documentation (also available at man 5 systemd.service):
Restart=
[…]
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 (including on core dump, but excluding the aforementioned four signals), when an operation (such as service reload) times out, and when the configured watchdog timeout is triggered. If set to on-abnormal, the service will be restarted when the process is terminated by a signal (including on core dump, excluding the aforementioned four signals), when an operation times out, or when the watchdog timeout is triggered.[…]
Setting this to
on-failureis the recommended choice for long-running services, in order to increase reliability by attempting automatic recovery from errors. For services that shall be able to terminate on their own choice (and avoid immediate restarting),on-abnormalis an alternative choice.
As an aside, instead of your current method of terminating the process by hand, you can explicitly tell systemd to stop the service with systemctl stop, which will bypass any Restart= settings.
Yes, you can use Restart=on-failure inside the unit’s Service section.
From systemd’s documentation (also available at man 5 systemd.service):
Restart=
[…]
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 (including on core dump, but excluding the aforementioned four signals), when an operation (such as service reload) times out, and when the configured watchdog timeout is triggered. If set to on-abnormal, the service will be restarted when the process is terminated by a signal (including on core dump, excluding the aforementioned four signals), when an operation times out, or when the watchdog timeout is triggered.[…]
Setting this to
on-failureis the recommended choice for long-running services, in order to increase reliability by attempting automatic recovery from errors. For services that shall be able to terminate on their own choice (and avoid immediate restarting),on-abnormalis an alternative choice.
As an aside, instead of your current method of terminating the process by hand, you can explicitly tell systemd to stop the service with systemctl stop, which will bypass any Restart= settings.
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!