Systemd вбиває службу відразу після запуску


15

Я записую файл системного блоку для OSSEC HIDS. Проблема полягає в тому, що коли systemd запускає сервіс, він негайно зупиняє їх.

Коли я використовую цю директиву ExecStart, все працює добре.

ExecStart=/var/ossec/bin/ossec-control start

Але коли я роблю невелике вдосконалення, я добре в журналах OSSEC, що він отримує SIG 15 після запуску.

ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start'

Якщо я зроблю ще одну невелику службу зміни, отримаю SIG 15 через 20 секунд.

ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start && sleep 20'

Отже, я думаю, що systemd вбиває / bin / sh процес після запуску служби, а bin / sh вбиває OSSEC.

Як я можу вирішити цю проблему?


1
Який тип послуги?
Віланд

@Wieland, я пробував просто і роздвоєння, але результат все одно той же.
Даніїл Свєтлов

Відповіді:


37

Невідповідність протоколу готовності

Як випливає з Віленда, Typeпослуга важлива. Цей параметр позначає, який протокол готовності systemd очікує, що служба зможе говорити. Передбачається, що simpleпослуга буде негайно готова. forkingСлужба береться , щоб бути готовим після його первісний процес розгалужується дитини , а потім завершує свою роботу. dbusСлужба береться , щоб бути готовим , коли на Desktop Bus з'являється сервер. І так далі.

Якщо ви не отримаєте протокол готовності, декларований в сервісному блоці, щоб відповідати тому, що робить служба, то все піде не так Невідповідність протоколу готовності призводить до того, що служби не запускаються належним чином, або (частіше) діагностуються системою (неправильно), як система не працює. Коли сервіс вважається таким, що не запускається systemd, гарантується, що кожен осиротілий додатковий процес служби, який, можливо, був запущений як частина відмови (з його точки зору), буде вбитий, щоб повернути послугу належним чином до неактивного держава.

Ви робите саме це.

Перш за все, прості речі: sh -cне відповідає Type=simpleабо Type=forking.

У simpleпротоколі, початковий процес береться бути процес обслуговування. Але насправді sh -cобгортка виконує фактичну програму обслуговування як дочірній процес . Так MAINPIDпіде не так і ExecReloadперестає працювати, для початку. При використанні Type=simpleпотрібно або використовувати, sh -c 'exec …'або не використовувати sh -c в першу чергу. Останнє частіше є правильним ходом, ніж думають деякі.

sh -cне відповідає Type=forkingжодному. Протокол готовності до forkingпослуги досить специфічний. Початковий процес повинен розщедрити дитину, а потім вийти. systemd застосовує тайм-аут до цього протоколу. Якщо початковий процес не розгортається протягом відведеного часу, він не може бути готовим. Якщо початковий процес не закінчується протягом відведеного часу, це теж є збоєм.

непотрібний жах, який є ossec-control

Що підводить нас до складного матеріалу: цього ossec-controlсценарію.

Виявляється, що це rcсценарій System 5, який розщеплює між 4 та 10 процесами, які самі поворотом і виходять. Це один із тих rcсценаріїв System 5, який намагається керувати цілим набором серверних процесів в одному єдиному скрипті з forциклами, умовами перегонів, довільним sleeps, щоб намагатися їх уникнути, режими відмов, які можуть заглушити систему в напівзапущеному стані, і всі інші жахи, які змусили людей вигадувати такі речі, як контролер системних ресурсів AIX та демомонтоли два десятиліття тому. І не будемо забувати прихований скрипт оболонки у двійковому каталозі, який він переписує на льоту, щоб реалізувати ідіосинкратичність enableта disableдієслова.

Отже, коли ви, /bin/sh -c '/var/ossec/bin/ossec-control start'що відбувається, це:

  1. systemd роздвоює те, що він очікує на сервісний процес.
  2. Це оболонка, яка роздрібнюється ossec-control.
  3. Що в свою чергу розщеплює від 4 до 10 онуків.
  4. Онуки все роз’їжджають і виходять по черзі.
  5. Праправнуки все роз’їжджають і виходять паралельно.
  6. ossec-control виходи.
  7. Перша оболонка виходить.
  8. Процеси обслуговування були великі-пра онуків, а тому , що цей шлях робочих матчів ні forking ніsimple протокол готовності, Systemd не вважає службу в цілому, не вдалося , і закриває його назад вниз.

Жоден з цих жахів насправді не потрібний за систематизованих. Нічого.

модуль обслуговування системного шаблону

Натомість пишемо дуже просту одиницю шаблону :

[Одиниця]
Опис = Сервер OSSEC HIDS% i
Після = network.target 

[Сервіс]
Тип = простий
ExecStartPre = / usr / bin / env / var / ossec / bin /% p-% i -t
ExecStart = / usr / bin / env / var / ossec / bin /% p-% i -f

[Встановити]
WantedBy = багатокористувач

Збережіть це як /etc/systemd/system/ossec@.service.

Різні фактичні служби - це оригінали цього шаблону, названого:

  • ossec@dbd.service
  • ossec@agentlessd.service
  • ossec@csyslogd.service
  • ossec@execd.service
  • ossec@agentd.service
  • ossec@logcollector.service
  • ossec@syscheckd.service
  • ossec@maild.service
  • ossec@analysisd.service
  • ossec@remoted.service
  • ossec@monitord.service

Потім функція включення та відключення надходить безпосередньо з системи управління послугамивиправленою помилкою RedHat 752774 ), без необхідності в прихованих скриптах оболонки.

 systemctl включити ossec @ dbd ossec @ agentlessd ossec @ csyslogd ossec @ maild ossec @ execd ossec @ analizad ossec @ logcollector ossec @ віддалений ossec @ syscheckd ossec @ monitord

Більше того, systemd дізнається про та відстежує кожну фактичну послугу безпосередньо. Він може фільтрувати їхні журнали за допомогою journalctl -u. Він може знати, коли окремий сервіс вийшов з ладу. Він знає, які послуги повинні бути включені та запущені.

До речі: Type=simpleі -fваріант є настільки ж правильним, як і у багатьох інших випадках. Дуже мало служб у дикій природі насправді сигналізує про свою готовність за допомогою мастила exit, і це теж не такі випадки. Але ось що forkingозначає тип. Служби в дикій природі в основному - лише роздвоєння та виїзд через помилкове уявлення про мудрість, що саме так слід робити. Насправді це не так. Це було не з 1990-х. Пора наздогнати.

Подальше читання


2
Дуже детальна відповідь! Я б також запропонував створити "групувальну" ціль, скажімо, ossec.target, котра Requires=всі необхідні екземпляри, а потім встановити PartOf=ossec.targetв ossec @ .service. Це дозволить запустити та зупинити ossec, запустивши та зупинивши ossec.target.
intelfx

@JdeBP, ух! Велике спасибі за таку детальну відповідь. Сподіваюсь, я зроблю цей блок і напишу тут про результати. Я хоч був, що мені буде легше. Але ти маєш рацію, ossec-control - це пекло.
Даніїл Світлов

1
У чому причина використання / usr / bin / env як обгортки?
Маріус Гедмінас

1

Keep Type = роздрібнення та надайте pid-файл, якщо служба запуску / додаток підтримує будь-який pid.

[Unit]
Description = "Запуск програми під час завантаження"
After = network.target syslog.target auditd.service

[Service]
Type = forking
PIDFile = / var / run / apache2 / apache2.pid
ExecStart = / etc / init.d / apache2 start
ExecStop = / etc / init.d / apache2 stop
StandardOutput = syslog
StandardError = syslog
Restart = on-
fail SyslogIdentifier = webappslog

[Install]
WantedBy = multi-user.target
Alias ​​= webapps


0

Дещо пов’язане з цим, у мене була система systemd, що, здається, що systemd «вбиває» її після 30-х.

systemctl status service-nameбуде показано main process exited, code=exited, status=1/FAILUREпісля закінчення 30-х.

Він би працював нормально "ізольовано" (як вручну в терміналі з тим же середовищем ).

Виявляється, це було

Type=forking
...
Environment=ABC="TRUE"
ExecStart=/path/to/my_script_to_spawn_process.sh

всередині my_script_to_spawn_process.shцього робилося

/bin/something > /dev/null 2>&1 &

який працює, але відкидає інформацію журналу виводу (зазвичай він надходить у файл, або, якщо не так, можливо journalctl).

Змінивши його, щоб увійти до іншого місця, як /bin/something > /tmp/my_file

то хвоста на /tmp/my_fileвиявлену фактичну причину. Що було (дотично), що ви не можете використовувати синтаксис, Environment=ABC="true"як ви можете в баші, це не повинно бути жодних лапок або ключового значення, все в лапках, як Environment="ABC=true"це було причиною того, що мій процес вийшов "у фазі його налаштування" приблизно через 30-і.


-4

Зауважимо, що демон-модель демонструється спрощеною і несумісною з багатьма існуючими демонами, які роблять багаторазове розгортання, виконання та налаштування. Найчастіше це демони, які починаються як root для налаштування речей, а потім переходять на менш привілейований UID для рутинної роботи. наприклад, ініціалізація Pid-файлів - це одне, що не спрацьовує під системою через проблеми з привілеями. Є обхідні шляхи (не виправлення), але це погано задокументовано.

Пояснення JdeBP вітається, але є неповним, і його твердження, що в усьому вина ossec-control просто не відповідає дійсності. Навіть досить тривіальні речі є проблематичними, наприклад, отримання непідготовлених ліній журналу для налагодження проблем або значущих повідомлень про помилки із самого systemd, коли це вбиває процеси.


1
Яке використання PID-файлів у будь-якому випадку? Якщо існує для даної послуги, може існувати фактичний процес з цим PID, а коли процес з правильним PID існує, він може бути, а може і не бути фактично очікуваною послугою.
JoostM
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.