Демонизируем скрипты. Краткий гайд как демонизировать простой bash скрипт.

JubyL3y

Кодер
Кодер
hackerville
Сообщения
13
Реакции
8
Введение

В операционных системах семейства Linux запущенные фоном скрипты и программы, которые не взаимодействуют напрямую с пользователем, называют демонами. Зачастую, но не всегда, демоны загружаются вместе с операционной системой. Самым ярким примером демона может служить сервер сетевого протокола или же менеджеры для периодического выполнения задач ( cron ).

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

Systemd - относительно новая подсистема иницализации и управления демонами Linux. Первый выпуск данной подсистемы был осуществлён в марте 2010 года, сама подсистема была призвана заменить существующую систему init. Данная подсистема оперирует таким понятием, как модуль. А аналогом демонов является понятие "служба", это один из подвидов модуля, далее в статье демоны будут пониматься как службы.

Рассмотрим поближе модули

Перед тем, как мы попробуем создать свой простейший демон, нужно изучить какие типы модулей systemd вообще бывают. Так как Linux соответствует концепции "Всё есть файл", то сами модули - это тоже обычные текстовые файлы с описанием конфигурации модуля. Модули именуются как <имя_модуля>.<тип_модуля>. Если имя модуля может быть выбрано пользователем произвольно и по сути не влияет на процесс работы с модулем, то с типом всё сложнее. От выбраного типа модуля зависит его функционал. Рассмотрим ниже типы модулей:
  • .target - модуль для группировки модулей, позволяет реализовывать концепцию уровней запуска
  • .service - отвечает за запуск сервисов (служб )или, как мы их называем, демонов;
  • .mount - отвечает за монтирование файловых систем;
  • .automount - по сути то же самое, что и mount, с той лишь разницей, что вызывается при фактическом обращении к точке монтирования;
  • .swap - модули для работы с файлом подкачки;
  • .timer - модули позволяющие организовать запуск других модулей по расписанию;
  • .socket — предоставляет службам поддержку механизма сокет-активации;
  • .slice — отвечает за создание контейнера cgroups;
  • .device — позволяет реагировать на подключение устройств;
  • .path — управляет иерархией файловой системы.
Для нас интересны 2 типа: .service и .timer.

Непосредственно создание демона

Теперь перейдём непосредственно к созданию демона. Я буду показывать пример создания демона на основе скрипта LogCleaner, который позволяет чистить директории от файлов, сохраняя структуру директорий. Работу разделим на 3 части:

  1. Скрипт установки нашего демона;
  2. Модуль типа .service для запуска нашего скрипта как демона;
  3. Модуль типа .timer для периодического запуска демона;
В конце статьи я оставлю ссылку на репозиторий, в котором будет лежать LogCleaner, а также все три файла описанные выше.
Итак, приступим к написанию скрипта для установки нашего демона.

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

Далее, чтобы при удалении пользователей в системе наш скрипт не удалился вместе с домашней директорией, выберем место хранения. Идеальным местом будет директория /opt, к ней имеют доступ все пользователи, а если скрипт вдруг нужно удалить, то достаточно будет убрать его оттуда ( главное не забыть удалить модули ).
После того, как мы скопировали скрипт в директорию opt, нужно скопировать наши модули. Все системные модули systemd хранит в директории /etc/systemd/system, туда их и скопируем.
Далее останется активировать таймер и добавить его в автозагрузку.
Таким образом получаем скрипт установки для оболочки bash:
Bash:
#!/bin/bash

SCRIPT="../log_cleaner.sh"
SERVICE="log_cleaner.service"
TIMER="log_cleaner.timer"
INSTALL_PATH="/opt"
SERVICE_INSTALL_PATH="/etc/systemd/system"

mkdir -p $INSTALL_PATH
cp $SCRIPT $INSTALL_PATH
chmod +x $INSTALL_PATH/log_cleaner.sh

cp $SERVICE $SERVICE_INSTALL_PATH
cp $TIMER $SERVICE_INSTALL_PATH

systemctl enable log_cleaner.timer
systemctl start log_cleaner.timer
2. Модуль типа .service
Основным файлом, который и будет запускать наш скрипт, является файл с расширением .service. Формат модулей systemd напоминает файлы формата .ini, в модулях systemd также есть секции и директивы, пример:
Код:
[Section]
Directive1=value
Directive2=value
.......
Для создания простого демона нам нужны всего 2 секции: Unit и Service. В секцию Unit мы добавим описание нашего сервиса, а в секции Service укажем какой файл нужно запускать и как. В итоге получим такой файл:
Код:
[Unit]
Description=Small script for directory cleaning with saving their structure.

[Service]
ExecStart=/opt/log_cleaner.sh
3. Модуль типа .timer
Последнее, что нам остаётся написать - это модуль типа .timer. Данный модуль будет запускать наш основной сервис раз в пять минут. Для данного модуля нам нужны секции Unit, Timer и Install.
В секции Unit также будет описание нашего сервиса.
В секции Timer мы добавим, что хотим запустить сервис через минуту после старта системы и после каждые 5 минут.
В секции Install мы укажем какой сервис мы хотим запускать.


В итоге получим такой файл модуля:
Код:
[Unit]
Description=Timer for running log_cleaner every 5 minutes

[Timer]
OnBootSec=1min
OnUnitActiveSec=5min

[Install]
WantedBy=timers.target
И всё, теперь после запуска скрипта установки наш сервис сразу начнёт работать.
На этом всё, замечания и какие-либо мысли по статье ( и возможно желаемые темы для рассмотрения в будущем ) жду в комменты.
Ссылка на репозиторий: https://github.com/JubyL3y/LogCleaner