Почему systemd не знает об отказе службы?

Почему systemd не знает об отказе службы?

Я пытаюсь подготовить приложения spring-boot (разработанные кем-то другим - я не программист на Java) на Ubuntu 18.04. Разработчик ранее добавил символические ссылки /etc/init.dдля включения службы - она ​​нормально запускается при загрузке. Однако если служба впоследствии даст сбой, systemd все равно сообщит, что она запущена:

[email protected]:/var/log/apps# systemctl status crm-service
● crm-service.service - LSB: crm-service
   Loaded: loaded (/etc/init.d/crm-service; generated)
   Active: active (exited) since Wed 2020-04-15 12:27:15 BST; 3h 56min ago
     Docs: man:systemd-sysv-generator(8)
  Process: 8656 ExecStop=/etc/init.d/crm-service stop (code=exited, status=0/SUCCESS)
  Process: 8703 ExecStart=/etc/init.d/crm-service start (code=exited, status=0/SUCCESS)

Apr 15 12:27:15 example.com systemd[1]: Starting LSB: crm-service...
Apr 15 12:27:15 example.com crm-service[8703]: /var/services/crm-service.conf: line 1: -Xms96M: command not found
Apr 15 12:27:15 example.com crm-service[8703]: Started [8747]
Apr 15 12:27:15 example.com systemd[1]: Started LSB: crm-service.

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

  1. Как заставить systemd увидеть истинное состояние службы? (она откроет прослушивающий сокет, но на случайном высоком порту)
  2. Есть ли способ заставить systemd попробоватьнежноперезапустить службу, которая, как известно, дала сбой?

решение1

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

Первая проблема, которую я вижу: systemd не использует скрипты запуска/остановки в /etc/init.d, это всего лишь дополнение совместимости для этого. Вместо этого systemd использует файлы юнитов, т.е. файл конфигурации для всех своих служб.

Модуль systemd sysv init compat эффективно генерирует файл unit для всех служб в /etc/init.d. Это не всегда нормально, поскольку в сценариях init отсутствует необходимая информация (или ее невозможно извлечь из них).

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

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

  • Как запускается ваше Java-приложение
  • Где это начинается?
  • От имени какого пользователя он запускается?

И воспроизвести ту же функциональность с помощью файла модуля.

Невозможно автоматически перезапустить initscripts из systemd, но это возможно из unit-файлов.

Обратите внимание, если программа Java случайно падает, это также является серьезной проблемой в ней. Все разумные фреймворки Java корректно обрабатывают свои собственные фатальные ошибки (они перехватывают все исключения, регистрируют их и продолжают работу).

Другая весьма вероятная ошибка в скрипте init заключается в том, что он не находит вашу JVM (скорее всего: /usr/bin/java), поэтому заменяет ее пустой строкой, в результате чего он пытается запустить флаги JVM как команду оболочки. Очевидно, что -Xms96Mв вашей системе нет команды, но она /usr/bin/java -Xms96M ...сработает.

Пример файла модуля для приложения Spring Boot:

[Unit]
Description=Crm Spring Boot App Example
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/java -Xms96M ...other flags... your.spring.boot.jar
User=exampleuser
Group=examplegroup
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=exampleapp
WorkingDirectory=/path/to/app/home

[Install]
WantedBy=multi-user.target
Alias=exampleapp.service

Этот файл модуля также перенаправляет стандартный вывод и ошибки процесса Java в системный журнал.

Для автоматического перезапуска приложения вставьте

RestartSec=5s
Restart=on-failure

в [Service]раздел.

Есть учебник по systemd наGoLinuxCloud.com.

Связанный контент