Как создать простейший сервис Systemd

Просмотров: 394

Захотел создать свой сервис для Systemd? Тебе сюда)
Article Image

   Здравствуйте все. Вы заметили, как меняется мир вокруг нас? Появляется что-то хорошее, что-то плохое. Прогресс не стоит на месте, все такое. Прогресс не обошел стороной и операционные системы. И уж тем более не обошел стороной наши любимые Линукс-дистрибутивы. Как вам известно, не так давно один человек изобрел такую штукенцию, под названием Systemd. В данный момент практически во всех дистрибутивах (если не во всех) используется systemd - менеджер системы и служб для Linux, совместимый со скриптами инициализации SysV и LSB. Systemd обеспечивает возможности агрессивной параллелизации, использует сокеты и активацию D-Bus для запускаемых служб, предлагает запуск демонов по необходимости, отслеживает процессы при помощи контрольных групп Linux, поддерживает мгновенные снимки и восстановление состояния системы, монтирование и точки монтирования, а также внедряет основанную на зависимостях логику контроля процессов сложных транзакций. Что же в нем такого? Да много чего, начиная с того, что там просто куча мегабайт документации. А раз документации так много. То и возможностей много, не так ли?

   Зачем он вообще нужен? Да черт его знает, мне например, и на SysV жилось неплохо. Но раз уж разработчики решили все за нас, то будем идти в ногу со временем. Да и к тому же, Systemd мне (уже) кажется лучше, чем другие системы инициализации. Да и запускается система в разы быстрее, в частности мой ноутбук стартует секунды за 4. Ну ладно, не буду я расписывать преимущества и недостатки. Сами почитаете в интернетах. Я же забыл совсем, о чем статью-то пишу….. А пишу я статью о том, как можно написать свой сервис для Systemd. Ранее я уже писал о том, как сделать аналог rc.local в Арче. Но там просто хауту, откуда можно скопипастить себе на комп скрипты, и радоваться, а вот как во всем этом разобраться, я не сказал. Так вот, короче говоря, перейдем к делу.
Systemd запускает сервисы описанные в его конфигурации, которая состоит из множества файлов (юнитов).

Все эти юниты расположены в трех каталогах:

/usr/lib/systemd/system/ – юниты из установленных пакетов (Squid, Apache и др.);
/run/systemd/system/ — юниты, созданные в run-time;
/etc/systemd/system/ — юниты, созданные системным администратором, сюда как раз мы можем класть свои конфиги-юниты.

Юнит представляет из себя текстовый файл с форматом, похожим на файлы .ini нашей «православной и любимой ОС».

 

[Название секции в квадратных скобках]
имя_переменной = значение



Для создания простого юнита нам надо описать всего три секции: [Unit], [Service], [Install]

В секции Unit описываем, что это за юнит:
(из названия переменных в принципе все понятно...)

Описание юнита:

Description=MyUnit


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

Запускать юнит после какого-либо сервиса или группы сервисов (например syslog.target):

After=syslog.target
After=squid.service


 


Для запуска сервиса необходим запущенный сервис Squid:

Requires=wicd.service


Для запуска сервиса желателен запущенный сервис Ssh:

Wants=sshd.service


В итоге переменная Wants получается чисто описательной.
Если сервис есть в Requires, но нет в After, то наш сервис будет запущен параллельно с требуемым сервисом, а не после успешной загрузки требуемого сервиса

В секции Service указываем какими командами и под каким пользователем надо запускать сервис:

Тип сервиса:

Type=simple 

(по умолчанию): systemd предполагает, что служба будет запущена незамедлительно. Процесс при этом не должен разветвляться. Не используйте этот тип, если другие службы зависят от очередности при запуске данной службы.

Type=forking

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

Также следует определить PIDFile=, чтобы systemd могла отслеживать основной процесс:

PIDFile=/var/run/myunit/service.pid


Рабочий каталог, он делается текущим перед запуском стартап команд:

WorkingDirectory=/etc/myunit


Пользователь и группа, под которым надо стартовать сервис:

User=myunit
Group=myunit



Переменные окружения:

Environment=RACK_ENV=production


Запрет на убийство сервиса вследствие нехватки памяти и срабатывания механизма OOM:
-1000 полный запрет (такой, например, у sshd стоит), -100 понизим вероятность.

OOMScoreAdjust=-100


Команды на старт/стоп и релоад сервиса

ExecStart=/usr/local/bin/bundle exec service -C /etc/myunit/config/service.rb --daemon
ExecStop=/usr/local/bin/bundle exec service -S /var/run/myunit/service.state stop
ExecReload=/usr/local/bin/bundle exec service -S /var/run/myunit/service.state restart


Тут есть одна тонкость — systemd настаивает, чтобы команда указывала на конкретный исполняемый файл. Надо указывать полный путь.

Таймаут в секундах, сколько ждать system отработки старт/стоп команд.

TimeoutSec=300



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

Restart=always



В секции [Install] опишем, в каком уровне запуска должен стартовать сервис

Уровень запуска:

WantedBy=multi-user.target


multi-user.target или runlevel3.target соответствует нашему привычному runlevel=3 «Многопользовательский режим без графики. Пользователи, как правило, входят в систему при помощи множества консолей или через сеть»

Вот и готов простейший стартап скрипт, он же unit для systemd:
myunit.service


 
[Unit]
Description=MyUnit
After=syslog.target
After=
squid.service
Requires=wicd.service
Wants=sshd.service
[Service]
Type=forking
PIDFile=/var/run/myunit/service.pid
WorkingDirectory=/etc/myunit
User=myunit
Group=myunit
Environment=RACK_ENV=production
OOMScoreAdjust=-1000
ExecStart=/usr/local/bin/bundle exec service -C /etc/myunit/config/service.rb --daemon
ExecStop=/usr/local/bin/bundle exec service -S /var/run/myunit/service.state stop
ExecReload=/usr/local/bin/bundle exec service -S /var/run/myunit/service.state restart
TimeoutSec=300
[Install] WantedBy=multi-user.target 
Кладем этот файл в каталог /etc/systemd/system/

Смотрим его статус systemctl status myunit
systemctl status myunit
● myunit.service - MyUnit
   Loaded: loaded (/etc/systemd/system/myunit.service; disabled; vendor preset: disabled)
   Active: inactive (dead)


Видим, что он disabled — разрешаем его
systemctl enable myunit
systemctl -l status myunit


Если нет никаких ошибок в юните — то вывод будет вот такой:

myunit.service - MyUnit
   Loaded: loaded (/etc/systemd/system/myunit.service; enabled)
   Active: inactive (dead)


Запускаем сервис 
systemctl start myunit

Смотрим красивый статус:
systemctl -l status myunit

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

systemctl daemon-reload

Не пытайтесь напрямую копипастить все, что тут написано. Пути у вас будут другие. И для запуска сервиса нужен сам сервис (исполняемый файл), не так ли?)))

В общем, творите. Будут вопросы, пишите мне на мыло (на главной странице блога написано).

Опубликовано 10 Октября 2015 в категории systemd

comments powered by HyperComments
Поиск по сайту:

Теги:

Популярные статьи:

Новости IT:

^ Наверх