Содержание

Что такое systemd: примеры использования

systemd — подсистема инициализации и управления службами в Linux, фактически традиционную подсистему init. systemctl - основной инструмент управления systemd.

Systemd опирается на современные Linux- технологии: cgroups, AutoFS, D-Bus, и при этом совместим с исторически устоявшимися механизмами: init- скриптами, стандартными командами shutdown, poweroff и т.п. Предоставляемый systemd функционал позволяет заменить не только систему инициализации, но и ряд других подсистем, в частности: cron, (x)inetd, xdm/kdm/gdm/…, частично даже SELinux как правильно отключить!! Для начинающих.

Модули Systemd

Чтобы понять разницу между всеми этими “модулями” или “юнитами”, надо вспомнить, что systemd, как и все остальное в Linux, является файлом. И все systemd-сущности являются разными файлами (например systemd службы хранят конфигурации в файле с расширением .service, а сокеты - .socket и т.д.). Systemd, если рассматривать как демон, управляет другими демонами и является первым демоном, который запускается во время загрузки ОС.

Базовым элементом systemd являются модули (units). Модули имеют имя и тип. Каждый модуль может требовать для своей работы другие модули, конфликтовать с модулями, запускаться только после или до определенного модуля (директивы конфигурации Requires, Conflicts, Before, After, Wants). Поскольку их конфигурация обычно загружается из файловой системы - названия модулей на самом деле представляют собой имена файлов. Например: модуль avahi.service считывается из конфигурационного файла с тем же именем и естественно, что он реализует работу с демоном Avahi. Из типов модулей определены:

Расположение файлов сервиса Systemd

Службы Systemd делят на две категории - системные службы, запускаемые от имени суперпользователя. Чтобы ими управлять, необходимо использовать sudo. Вторая категория - пользовательские службы, запускаемые от имени конкретного пользователя. Этот пользователь может иметь полный контроль без sudo.

Файлы системных служб находятся в

/usr/lib/systemd/system
/lib/systemd/system
/etc/systemd/system

Например, в примере ниже видно что физически файл находится в /usr/lib/systemd/system/, а из других каталогов просто ссылки

stat /etc/systemd/system/multi-user.target.wants/postgresql-13.service
  File: ‘/etc/systemd/system/multi-user.target.wants/postgresql-13.service’ ->/usr/lib/systemd/system/postgresql-13.service’

Файлы пользовательских служб можно найти в:

/usr/lib/systemd/user
/lib/systemd/user
/etc/systemd/user
$USER/.config/systemd/user

Причем файлы сервисов поставляемые с пакетами обычно находятся в каталогах /lib и /usr/lib, а в /etc/ расположены модифицированные файлы юнитов переопределяющие стандартные настройки

Стандартное использования systemd (systemctl)

systemctl - основной инструмент управления systemd.

systemctl start nginx
systemctl stop nginx
systemctl status nginx
systemctl restart nginx
systemctl is-enabled nginx
systemctl enable nginx

Подкоманда enable не запускает службу, а только помечает ее для автоматического запуска при загрузке. Чтобы включить и запустить службу одновременно, используйте параметр –now

systemctl enable --now nginx
systemctl disable apparmor

В строке Loaded видим ключ enabled.

 systemctl status apparmor
   Loaded: loaded (/etc/init.d/apparmor; bad; vendor preset: enabled)
systemctl mask nginx
systemctl list-dependencies nginx
systemctl -t service -a
или так
systemctl --type=service -a

Список запущенны юнитов в Linux.

# systemctl list-units
# systemctl status syslog.target
syslog.target - Syslog
	  Loaded: loaded (/lib/systemd/system/syslog.target; static)
	  Active: active since Thu, 01 Mar 2012 16:18:25 +0000; 18h ago

Рассмотрим модуль файла планировщика cron

Файл модуля cron находится по адресу /lib/systemd/system/cron.service.

[Unit] - директива, указывающая systemd, что эта часть файла является описательной, указывает параметры запуска и т.д.
Description=Regular background program processing daemon - описание юнита
Documentation=man:cron(8) - указание пути к документации
After=remote-fs.target nss-user-lookup.target - параметр, указывающий, что данный юнит должен запускаться после (after) модуля, указанного справа от "=".
 
[Service] - блок конфигурации юнита
EnvironmentFile=/etc/default/cron - файл окружения
ExecStart=/usr/sbin/cron -f $EXTRA_OPTS - команда для старта
IgnoreSIGPIPE=false - параметр для игнорирования SIGPIPE сигнала (SIGPIPE — сигнал, посылаемый процессу при записи в соединение (пайп, сокет) при отсутствии или обрыве соединения с другой (читающей) стороной.)
KillMode=process - указывает, как "убивать" процесс.
Restart=on-failure - указание, когда необходимо перезагружать сервис.
 
[Install] - блок, описывающий информацию об установке юнита (нужен для команд systemctl enable/disable)
WantedBy=multi-user.target - данная директива, является наиболее распространенным способом
определения того, как юнит должен быть включен, от чего зависит.

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

Создайте скрипт, который вы хотите запускать и дать файлу права на исполнение (chmod +x). В этом примере создан тестовый файл /usr/sbin/love.sh, с таким содержимым:

#!/bin/bash
while true
do
  printf "Make love,not war\n"
sleep 60
done

Создайте файл /etc/systemd/system/love.service на вашем тестовом Debian:

[Unit]
Description=My first super program
 
[Service]
#fail
ExecStop=/bin/kill -9 $MAINPID
#StandardOutput=null
#success
ExecStart=/bin/bash /usr/sbin/love.sh
 
[Install]
WantedBy=multi-user.target

Все готово, теперь для запуска введите:

systemctl daemon-reload
systemctl start love.service

Для проверки того что все работает, убедитесь что служба работает, командой:

systemctl status love.service

И также проверьте системный журнал syslog на наличие строки "Started My first super program", командой:

tail -f /var/log/syslog
 
Dec  6 23:32:34 dark systemd[1]: Started My first super program.
Dec  6 23:32:34 dark bash[2672]: Make love,not war
Dec  6 23:32:39 dark bash[2672]: Make love,not war

Если раскомментировать строку StandardOutput=null, то вывод нашего скрипта love.sh (Make love,not war) перестанет писаться в файл syslog.

Пример: Автозагрузка контейнеров Docker в ОС при помощи systemd

Ваш сервер перезагрузился и все запущенные контейнеры Docker остановились. Чтобы избавиться от необходимости вручную запускать их, можно настроить автозапуск контейнеров. Для этого следует создать текстовые файлы со специальным форматом для сервиса systemd. Рассмотрим пример автозапуска контейнера my-db, для этого создадим файл

nano /etc/systemd/system/my-db.service

В этом файле:

[Unit]
Description=My docker container my-db-container
# для успешного запуска нашего контейнера сначала должна быть запущена служба Docker
Requires=docker.service
After=docker.service
 
[Service]
# Если служба завершает работу всегда перезапускать её
Restart=always
ExecStartPre=-/usr/bin/docker stop 
ExecStartPre=-/usr/bin/docker rm my-db-container
ExecStart=/usr/bin/docker run --name my-db-container my-docker-image
ExecStop=/usr/bin/docker stop my-db-container
 
[Install]
WantedBy=multi-user.target

После этого остается перезапустить демон systemcmd и включить автозагрузку контейнера mydb, набрав в терминале поочередно команды:

systemctl daemon-reload
systemctl start my-db.service
systemctl enable my-db.service

Использование таймеров systemd вместо заданий cron

Systemd-таймеры и задания cron, могут, в заданное время, вызывать выполнение различных действий в системе. Например — запуск скриптов командной оболочки или программ. Таймеры могут срабатывать, например, раз в день, причём — только по понедельникам. Ещё один пример — срабатывание таймера каждые 15 минут в рабочее время (с 8 утра до 6 вечера). Но таймеры systemd могут кое-что такое, что недоступно заданиям cron. Например, таймер может вызвать скрипт или программу через заданное время после некоего события. Таким событием может быть загрузка системы или запуск systemd, завершение предыдущей задачи или даже завершение работы сервиса, вызванного ранее по таймеру.

Получить список всех таймеров в системе

systemctl status *timer

Таймеры systemd обладают другими возможностями, которых нет у заданий cron, «одноразовых» или повторяющихся, которые вызываются только с привязкой к реальному времени и к реальным датам. Таймеры systemd можно настроить так, чтобы они вызывались бы на основании изменения состояния других юнитов systemd. Например, таймер можно настроить так, чтобы он срабатывал бы через заданное время после загрузки системы, после входа в неё пользователя, или через заданное время после активации определённого сервиса. Такие таймеры называют монотонными (monotonic). Эти таймеры сбрасываются после каждой перезагрузки системы.

Таймеры systemd можно использовать для решения тех же задач, которые решают с помощью заданий cron. Но systemd даёт больше гибкости в плане настройки календарных и монотонных таймеров.

Настройка DNS Systemd resolvectl (systemd-resolve)

Система инициализации Systemd имеет собственный распознаватель systemd-resolved, который запускается по умолчанию. Указываем systemd-resolved IP-адреса DNS-серверов, для разрешения доменных имен:

nano /etc/systemd/resolved.conf
[Resolve]
DNS=8.8.8.8 8.8.8.4 1.1.1.1

Для применения изменеий выполните

systemctl restart systemd-resolved.service

Утилиты не использующие библиотечные вызовы, обращаются к DNS-серверам напрямую из файла /etc/resolv.conf.

Команда systemd-resolve была переименована в resolvectl. Чтобы посмотреть состояние службы запустите команду

resolvectl status

systemd-analyze blame список служб при загрузке ОС

Команда systemd-analyze blame в Linux показывает список служб и программ, запускаемых при загрузке системы, в порядке убывания времени, которое каждая из них занимает для завершения. Это позволяет идентифицировать процессы, которые могут замедлять загрузку системы, и оптимизировать их при необходимости.

~# systemd-analyze blame
13.832s systemd-networkd-wait-online.service
 6.071s geoipupdate.service
 2.396s redis-server.service
 1.975s postfix@-.service
 1.497s certbot.service
 1.348s apt-daily.service
 1.051s logrotate.service
  874ms apt-daily-upgrade.service
  611ms mariadb.service
  423ms dev-sda3.device
  393ms networkd-dispatcher.service
  383ms fstrim.service
  377ms php8.1-fpm.service
  352ms man-db.service
  349ms ufw.service
  333ms phpsessionclean.service
  315ms dpkg-db-backup.service
  228ms nginx.service
...