Создание сервиса systemd linux

Создание сервиса systemd linux

systemd allows you to create and manage services in extremely powerful and flexible ways. This page will only cover the most basic uses; for full details, please see the systemd manual pages.

As a modern service manager, systemd builds on the concepts, knowledge and experience of previous and contemporary service managers such as daemontools, runit and nosh. If you’ve ever used any of these, you will probably find systemd’s service management features to be easy and comfortable.

If your only experience is with System V init.d scripts, you may be confused at first. Init.d scripts use many ugly hacks (for example, PID files, and all of the infrastructure surrounding PID files) to work around the fundamental brokenness of sysv-rc. If you have grown accustomed to these hacks, you may first need to unlearn some bad habits.

Unit files

If you’re creating a brand new unit file for your service, you must first come up with a name. The name you select must not collide with any existing service name, because your unit file will take precedence over any Debian default unit file with the same name. For the purposes of this page, we’ll use the name myservice.

Create your service’s unit file with the «.service» suffix in the /etc/systemd/system directory. In our example, we will be creating a /etc/systemd/system/myservice.service file.

Unit files use the «.INI» syntax, with section headers in square brackets, followed by variable declarations within that section, one per line. We’ll need three sections: Unit, Service and Install. For now, don’t worry about the separate meaning of each section. Just follow the examples to see which variables go in which section.

Service type

The first thing you must identify is what type of service you will be managing. systemd.service(5) lists the types: simple, forking, oneshot, dbus, notify or idle.

Most services should use the simple type, which means a program that runs in the foreground. If your service normally runs itself in the background, search the documentation to see if it has an option to disable that. Running in the foreground is preferred.

If you can’t prevent the daemon from forking itself into the background, then you must use the forking type.

Also, decide whether you want systemd to restart (Restart=) your service when it exits. The default is no (which is different from daemontools). The other choices are always, on-success, on-failure, on-abnormal, on-watchdog or on-abort. You can even set a delay before systemd restarts it (with RestartSec=).

Читайте также:  Английский русский переводчик linux

Environment setup

  • WorkingDirectory= (change directory before executing processes)
  • RootDirectory= (chroot)
  • User=
  • Group=
  • UMask=
  • Environment= (variables)
  • . and many, many other options

Logging may also be configured here, if you need to use something other than systemd’s native logging (accessible through journalctl(1)).

Service dependencies

Putting it together

For our basic service, which uses the network, and should be run every time we boot into «multi-user.target» or higher (i.e. all normal system boots, with or without a graphical Display Manager), we end up with a service unit file like this:

# Contents of /etc/systemd/system/myservice.service [Unit] Description=My Service After=network.target [Service] Type=simple Restart=always ExecStart=/usr/local/bin/myservice [Install] WantedBy=multi-user.target

Making it go

After creating or modifying any unit files, we must tell systemd that we want it to look for new things:

Our new service should be recognized at this point, but it won’t run yet. We need to do two more things. First, tell systemd to enable it, so that it will start every time we boot:

systemctl enable myservice.service
systemctl start myservice.service

Note that you don’t get feedback from this command, because all it does it send a message to systemd telling it to start your service. The command you typed doesn’t hang around to see what happens next. You may use systemctl status myservice.service (or systemctl status myservice) to check on your service, to make sure it seems OK.

Also note that systemctl status myservice gives more information if you run it as root, compared to running it as a normal user.

Источник

Как создать свой сервис для Linux

linux

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

Основы создания сервиса Linux

Если вы еще никогда не делали свои сервисы, начнем с основ. Systemd оперирует абстрактными единицами (unit), которые бывают разных типов, могут предоставлять различные ресурсы (процессы, сокеты, абстрактные «цели») и требовать других ресурсов для запуска.

Самый распространенный вид ресурса — сервис (service). Файлы с описаниями сервисов и всего прочего лежат в каталоге / lib / systemd / system / . Чтобы systemd нашел новый сервис, достаточно положить в этот каталог свой файл. Если этот сервис ранее не существовал, systemd прочитает файл и загрузит его в память. Однако, если вы редактируете файл ранее запущенного сервиса, не забудьте заставить systemd перечитать файлы командой sudo systemctl daemon — reload !

Сервисы типа oneshot — долой rc.local

Когда-то основным способом добавить выполнение команд в загрузку системы было дописать их в /etc/rc.local. Очевидный недостаток — нет способов следить, насколько успешно они выполнились. В systemd легко создать для такой цели свой сервис типа oneshot, и им можно будет управлять через systemctl, как любым другим. В этом случае systemd выполнит команду и посчитает запуск сервиса успешным, если она завершилась с кодом ноль.

Читайте также:  Служба печати линукс минт

Сохраним следующий файл в / lib / systemd / system / dumb — test . service :

Дополнительных действий не требуется, и теперь вы можеыр делать с ним все то же, что с системными сервисами: запустить с помощью sudo systemctl start dumb — test . service , поставить на загрузку с помощью sudo systemctl enable dumb — test . service и так далее.

Создание сервиса из любой программы

Любой долгоживущий процесс можно легко превратить в сервис с помощью опции Type = idle . В этом случае systemd перехватит стандартные потоки ввода-вывода и будет следить за жизнью процесса.

Для демонстрации напишем программу на Python, которая просто выводит сообщение в бесконечном цикле. Сохраним в / usr / local / bin / test . py следующее:

Затем создадим для нее файл сервиса в / lib / systemd / system / smart — test . service :

Теперь можно запустить наш сервис и убедиться, что он работает:

Loaded : loaded ( / usr / lib / systemd / system / smart — test . service ; static ; vendor preset : disabled )

Стандартный вывод программы пишется в journald, и его можно увидеть в journalctl — u smart — test . Ради интереса посмотрим на работу опции Restart = on — failure . Остановим наш процесс с помощью kill — 9 $ < Main PID >и заглянем в логи:

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

Зависимости и порядок запуска

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

Порядок запуска сервисов

Порядок запуска сервисов определяется опциями Before и After . Если в настройках сервиса foo написано After = bar . service и оба сервиса должны запуститься, то systemd сначала выполнит попытку запустить bar, а затем foo.

Однако опция After = bar . service сама по себе не поставит сервис на загрузку. Более того, она никак не повлияет на решение запускать foo, даже если запуск bar завершится неудачей.

Причина существования этих опций — способность systemd запускать сервисы параллельно.

Для примера возьмем типичный веб-сервер с набором из веб-приложения FCGI, СУБД и обратного прокси. В каком порядке запускать процесс FCGI и обратный прокси, не так важно. Запросы будут работать, только когда они оба запущены, но «неверный порядок» никак не помешает им запуститься.

Если веб-приложение требует данных из базы для инициализации, то мало убедиться, что и процесс FCGI, и СУБД запущены, — приложение нужно запускать только после полного запуска СУБД. Именно для этих случаев и предназначены опции Before / After .

Читайте также:  Linux deploy failed to mount

Зависимости

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

Мягкие зависимости указываются с помощью опции Wants = в секции [ Unit ] . Пример из sshd . service :

Цель sshd — keygen . target , очевидно, генерирует ключ хоста, если он отсутствует. Технически sshd не сможет запуститься без ключа хоста, поэтому, почему авторы решили сделать зависимость мягкой, можно только догадываться. Возможно, они посчитали, что в большинстве случаев ключ уже существует и устаревший ключ лучше неработающего SSH.

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

Жесткие зависимости можно указать с помощью опции Requires . К примеру, в systemd — journal — flush . service есть опция Requires = systemd — journald . service — очевидно, отправить команду journald невозможно, пока он не запущен.

У этой опции существуют вариации, например RequiresMountsFor . Посмотрим в файл logrotate . service :

Для работы logrotate нужен доступ к каталогу с логами и больше ничего. Опция RequiresMountsFor =/ var / log позволяет выразить именно это: сервис запустится, как только будет примонтирован каталог, содержащий путь / var / log , даже если он находится не в корневом разделе.

Внедрение в зависимости к чужим сервисам

В системах с System V init добавить что-то в зависимости к чужому сервису можно было, лишь отредактировав его скрипт. Такие изменения, очевидно, не переживут обновления системы, поэтому сделать их постоянными можно было бы только пересборкой пакета.

В systemd есть несколько способов решить эту проблему. Если нужно именно внедриться к кому-то в зависимости, можно попробовать опции обратных зависимостей: WantedBy и RequiredBy . Они должны находиться в секции [ Install ] , а не [ Unit ] . Подводных камня здесь два: они обрабатываются только при установке сервиса с помощью systemctl enable и, как все в systemd, не всегда нормально работают во всех версиях.

Второй вариант, который позволяет менять любые настройки: скопировать файл сервиса в / etc / systemd / system / . Если один файл присутствует в обоих каталогах, то файл из / etc / systemd / system имеет приоритет.

Третий, менее радикальный вариант: создать файл вида / etc / systemd / system / $ < unit >. d / local . conf и прописать туда только нужные настройки.

Для примера притворимся, что наш сервис smart-test вовсе и не наш, и добавим ему в зависимости sshd.service третьим способом. Создадим файл / etc / systemd / system / smart — test . service . d / local . conf со следующим содержанием:

Источник

Оцените статью
Adblock
detector