инициализация службы не удается включить после генерации файла службы systemd

Вопрос или проблема

Я пытаюсь устранить проблему с тем, что служба sysVinit не запускается должным образом при загрузке в среде systemd. Я обнаружил, что когда в /etc/systemd/system/ отсутствуют файлы службы или переопределения для указанной службы, она правильно автозапускается. В этом случае, как я понимаю, systemd должен динамически загружать скрипт запуска, читая “наследственные” скрипты sysvinit, присутствующие в системе, хотя я не на 100% уверен в этом.

Меня смущает то, что как только я передаю опцию edit –full в systemctl для указанной службы, в /etc/systemd/system/ генерируется обычный файл, и указанная служба теперь не может автозапуститься при загрузке. Использование опции редактирования и попытка добавить какие-либо переопределения также, похоже, приводит к тому, что служба не запускается.

Примеры, если нужно, приведены ниже…

Пример работы системы

Служба (на Centos), в этом примере названная “ProgramExample”, имеет скрипт инициализации, размещенный в /etc/init.d/programexample и также /etc/rc.d/init.d/programexample:

# ls -l /etc/rc.d/init.d/programexample
-rwxr-xr-x. 1 root root 2264 Mar 29 14:11 /etc/rc.d/init.d/programexample

Файл службы отсутствует в /etc/systemd/system/:

# ls -lh /etc/systemd/system/programexample.service
ls: cannot access /etc/systemd/system/programexample.service: No such file or directory

Вывод состояния systemctl в этой конфигурации:

# systemctl status programexample.service
● programexample.service - LSB: Start Program Example at boot time
   Loaded: loaded (/etc/rc.d/init.d/programexample; bad; vendor preset: disabled)
   Active: active (exited) since Wed 2017-03-29 15:53:06 CDT; 14min ago
     Docs: man:systemd-sysv-generator(8)
  Process: 1297 ExecStart=/etc/rc.d/init.d/programexample start (code=exited, status=0/SUCCESS)

Mar 29 15:53:05 centos7-box systemd[1]: Starting LSB: Start ProgramExample at boot time...
Mar 29 15:53:05 centos7-box su[1307]: (to programexample) root on none
Mar 29 15:53:06 centos7-box programexample[1297]: ProgramExample (user programexample): имя экземпляра установлено на centos7-box
Mar 29 15:53:06 centos7-box programexample[1297]: публичный базовый URI экземпляра установлен на https://192.168.0.148.programexample.net/programexample/
Mar 29 15:53:06 centos7-box programexample[1297]: часовой пояс экземпляра установлен на US/Central
Mar 29 15:53:06 centos7-box programexample[1297]: запуск java-сервисов
Mar 29 15:53:06 centos7-box programexample[1297]: Сервер ProgEx запущен.
Mar 29 15:53:06 centos7-box systemd[1]: Started LSB: Start ProgramExample at boot time.

При вышеизложенной конфигурации, без каких-либо файлов, созданных/размещенных в /etc/systemd/system/, служба ProgramExample автозапускается должным образом.

Как только используется systemctl edit --full (или просто edit):

После того как любые изменения были переданы в systemctl, я наблюдал следующее:

  • Обычный файл или каталог переопределения будет размещен в /etc/systemd/system/
  • Указанная служба, в данном случае ProgramExample, не запускается при загрузке.
  • Я не смогу “включить” указанную службу, используя systemctl

Вывод состояния systemctl в этой конфигурации (после редактирования):

# systemctl status programexample.service
● programexample.service - LSB: Start ProgramExample at boot time
   Loaded: loaded (/etc/rc.d/init.d/programexample; static; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:systemd-sysv-generator(8)

Это файл службы, который генерируется и размещается в /etc/systemd/system/ при использовании опции edit --full:

# Автоматически сгенерировано генератором systemd-sysv

[Unit]
Documentation=man:systemd-sysv-generator(8)
SourcePath=/etc/rc.d/init.d/programexample
Description=LSB: Start ProgramExample at boot time
Before=runlevel2.target
Before=runlevel3.target
Before=runlevel4.target
Before=runlevel5.target
Before=shutdown.target
Before=adsm.service
After=all.target
After=network-online.target
After=postgresql-9.4.service
Conflicts=shutdown.target

[Service]
Type=forking
Restart=no
TimeoutSec=5min
IgnoreSIGPIPE=no
KillMode=process
GuessMainPID=no
RemainAfterExit=yes
ExecStart=/etc/rc.d/init.d/programexample start
ExecStop=/etc/rc.d/init.d/programexample stop
ExecReload=/etc/rc.d/init.d/programexample reload

Что здесь происходит? Правильно ли я понимаю, что без обычного файла службы и/или каталога переопределения в /etc/systemd/system/ systemd динамически читает эту информацию из скрипта инициализации указанной службы? Я пробовал множество вариантов редактирования файла службы в /etc/systemd/system/ и оставлял файл по умолчанию на месте, и не смог заставить автозапуск работать или службу перейти в состояние “включена”.

Я считаю, что было бы предпочтительно иметь файл .service для конфигураций systemd вместо того, чтобы полагаться на systemd для чтения заголовков LSB из скрипта инициализации по причинам совместимости и параллелизма, но стандартный файл, который создаёт systemd, не запускается и не включается, наряду с множеством других более простых вариантов файла .service, которые я пробовал.

Я теперь обнаружил, что проблема заключалась в том, что файл службы, автоматически созданный systemd-sysv-generator, не содержит раздела install с опцией WantedBy. Я добавил следующее в созданный файл в /etc/systemd/system/programexample.service, что позволило мне правильно включить службу:

[Install]
WantedBy = multi-user.target

После этого я выполнил

systemctl daemon-reload

чтобы убедиться, что файл службы был прочитан systemd.

Теперь я получил правильное уведомление о том, что моя служба на самом деле символически связана где-то, чтобы быть “включенной”:

[root@centos7-box ~]# systemctl enable programexample.service
Создана символическая ссылка из /etc/systemd/system/multi-user.target.wants/programexample.service на /etc/systemd/system/programexample.service.

Эта ссылка помогла мне лучше понять файл службы.

Мне не нравится, что systemd-sysv-generator по умолчанию не включает раздел install с опцией WantedBy. Если systemd может динамически читать заголовки LSB и правильно запускать службы при загрузке, почему он не генерирует файл службы соответственно? Думаю, некоторые “старые болезни” systemd были ожидаемы.

Обновление 7 июля 2020 года:

Работая с Debian Buster и пытаясь включить устаревшую службу SysVInit, я получил это замечательное сообщение, которое, я считаю, сэкономило бы мне время, когда я сталкивался с этой проблемой в 2017 году:

Синхронизация состояния службы programexample.service с скриптом службы SysV с 
/lib/systemd/systemd-sysv-install.
Выполняется: /lib/systemd/systemd-sysv-install enable programexample
Файлы единиц не имеют конфигурации установки (WantedBy=, RequiredBy=, Also=,
Alias= настройки в разделе [Install], и DefaultInstance= для шаблонных единиц). 
Это означает, что их не следует включать с помощью systemctl. 
Возможные причины наличия таких единиц:

• Единица может быть статически включена за счет создания символической ссылки из другой единицы
  в /wants/ или 
.requires/ директории.
• Цель единицы может заключаться в том, чтобы выступать в качестве помощника для другой единицы, у которой есть
  зависимость.
• Единица может быть запущена по мере необходимости путем активации (сокет, путь, таймер,
  D-Bus, udev, вызов systemctl по сценарию и т.д.).
• В случае шаблонных единиц единица предназначена для включения с заданным
  именем экземпляра.

В моем случае проблема возникла из-за наличия двух разных версий Java в системе, одна из которых (Oracle JDK) была установлена позже установки Jenkins в моей системе. Я выполнил команду alternatives -config java и установил Java на версию open JDK, которая была установлена вместе с Jenkins, и перезапустил службу сервера Jenkins. Вот и все.

Ответ или решение

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

Причины проблемы

  1. Отсутствие раздела [Install]: Основная причина, почему ваша служба не могла быть активирована и не запускалась при загрузке, заключается в том, что автоматически сгенерированный файл службы, созданный systemd-sysv-generator, не содержал раздела [Install]. Этот раздел необходим для того, чтобы указывать, в какой цели (target) должна быть включена служба. Например, добавление WantedBy=multi-user.target в этот раздел позволяет системе понять, что служба должна быть активирована при достижении уровня многопользовательского режима.

  2. Генерация файлов служб: При отсутствии специального файла службы в /etc/systemd/system/, systemd автоматически генерирует его на основе скриптов SysVinit, что позволяет поддерживать совместимость с более старыми системами. Однако, как вы заметили, система не всегда создает все необходимые секции, что может привести к проблемам с автозапуском.

  3. Проблемы с версиями Java: В вашем обновлении указано, что служба Jenkins не могла запуститься из-за конфликтов между различными версиями Java. Это подчеркивает важность управления версиями программного обеспечения в системах, где многие сервисы могут зависеть от общего окружения.

Решения проблемы

  1. Добавление секции [Install]: После создания файла службы вручную или редактирования автоматически созданного файла, добавьте следующий код в секцию [Install]:

    [Install]
    WantedBy=multi-user.target

    Это позволит системе понять, что служба должна быть запущена при многопользовательском доступе.

  2. Перезагрузка демона systemd: После внесения изменений, всегда выполняйте команду:

    systemctl daemon-reload

    Это позволит systemd перезагрузить конфигурацию служб и учитывать все изменения в файлах.

  3. Включение службы: После обновления файла и перезагрузки демона, выполните команду включения службы:

    systemctl enable programexample.service

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

  4. Проверка статуса: После всех изменений, проверьте статус службы командой:

    systemctl status programexample.service

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

Заключение

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

Если у вас возникнут дополнительные вопросы или потребуется помощь, не стесняйтесь обращаться к сообществу или профессионалам для получения более детальной поддержки.

Оцените материал
Добавить комментарий

Капча загружается...