Содержание

systemd

https://www.freedesktop.org/software/systemd/man/index.html
Set up self-healing services with systemd
Demystifying Systemd
https://systemd-by-example.com/ - примеры с тестами в браузере.

Unit-файл

https://www.freedesktop.org/software/systemd/man/systemd.unit.html

Это скрипт запуска приложения - как его запускать, под каким пользователем и т. д. Системные юнит-файлы лежат в /lib/systemd/system (есть варианты), свои можно создавать в /etc/systemd/system. Также в /etc/systemd/system находятся ссылки на системные юнит-файлы, эти ссылки делаются с помощью команды systemctl enable. После создания юнит-файла можно управлять запуском приложения - например, добавить в автозагрузку.

Пример unit-файла:

/etc/systemd/system/multi-user.target.wants/sshd.service
[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
# After - запускать после network.target и sshd-keygen.service
After=network.target sshd-keygen.service
# Wants - слабая зависимость: sshd-keygen.service должен запускаться, но sshd запустится вне зависимости от результатов sshd-keygen.
Wants=sshd-keygen.service
 
[Service]
EnvironmentFile=/etc/sysconfig/sshd # Файл с переменными
ExecStart=/usr/sbin/sshd -D $OPTIONS # Строка запуска, $OPTIONS - это из EnvironmentFile
ExecReload=/bin/kill -HUP $MAINPID # Строка для reload
KillMode=process # Как systemd будет останавливать сервис. Здесь: остановить только основной процесс, но не трогать дочерние (чтобы уже запущенные сессии ssh не отвалились)
Restart=on-failure # Перезапуск сервиса при сбое
RestartSec=42s # Через сколько перезапускать
 
[Install]
WantedBy=multi-user.target # Работать под runlevel multi-user

https://fedoramagazine.org/systemd-converting-sysvinit-scripts/

man systemd.unit # Справка по юнитам
cat /proc/$(pidof cron)/environ # Вывести переменные процесса cron
journalctl -u cron.service -n 10 # Лог (последние 10 записей)
journalctl -u cron.service --since yesterday # Лог со вчерашнего дня

Типы юнитов systemd

target # группирует модули
service # отвечает за запуск сервисов (служб) и поддерживает вызов интерпретаторов для исполнения пользовательских скриптов
mount # занимается монтированием файловых систем
automount # автомонтирование файловых систем, используется при обращении к точке монтирования
swap # отвечает за подключение файла подкачки
timer # запускает модули по расписанию, аналог cron
socket # запуск модуля при подключении к сокету
slice # группировка других модулей в контейнер (дерево) cgroups
device # использует реакцию на подключение какого-либо устройства
path # запуск модуля по событию доступа по конкретному пути в файловой системе

Управление процессами systemd

systemctl list-units --type service --all # просмотр всех юнитов в системе
systemctl list-unit-files --type service
systemctl start name # запустить сервис
systemctl stop name # остановить сервис
systemctl restart name # перезапустить сервис
systemctl status name # посмотреть статус сервиса
systemctl reload name # перечитать конфигурацию
systemctl daemon-reload # перечитать конфигурацию для всех
systemctl try-restart name # перезапустить, если запущен
systemctl enable name # включить автозапуск сервиса
systemctl disable name # отключить автозапуск сервиса
systemctl list-unit-files --type service # список установленных юнит-файлов сервисов

Зависимость между юнитами и порядок запуска

Перед запуском юнит может wants или requires другой юнит. Разница:

Для чего нужен wants? Например, в sshd.service есть Wants=sshd-keygen.service. Sshd-keygen.service генерит ключи для сервера, если их нет. Если они есть, то sshd-keygen.service завершается с ошибкой, которая говорит о наличии ключей, но это не должно влиять на запуск sshd.service.

Wants и requires - это не порядок запуска, юниты запускаются вместе. За порядок запуска в systemd отвечают параметры Before и After.

В примере sshd.service запустится только после того, как поднялась сеть и запустился sshd-keygen.

Wants=sshd-keygen.service
After=network.target sshd-keygen.service

https://fedoramagazine.org/systemd-unit-dependencies-and-order/

Target unit

Используется для связи и группировки других юнитов вместе, чтобы описать желаемое состояние системы. Некоторые из этих юнитов могут быть сервисами, некоторые - другими таргетами со своими группами юнитов.

В примере нет выполняемой команды, таргет работает как связующее звено между другими таргетами.

multi-user.target
[Unit]
Description=Multi-User System
Documentation=man:systemd.special(7)
Requires=basic.target
Conflicts=rescue.service rescue.target
After=basic.target rescue.service rescue.target
AllowIsolate=yes

AllowIsolate - система рассматривает юнит как загрузочную цель (команда systemctl isolate). Посмотреть текущую загрузочную цель - systemctl get-default.

Таргет может иметь каталог .wants, в котором хранятся ссылки на юниты (не только сервисы, но и другие таргеты), которые будут запущены при старте основного таргета. Например, материнский таргет лежит по пути /usr/lib/systemd/system/multi-user.target, значит, каталог будет /usr/lib/systemd/system/multi-user.target.wants. Каждый юнит в этом каталоге может иметь собственные зависимости или опции типа Requires, поэтому можно создать довольно сложную иерархическую структуру.

systemd-resolve

Если в /etc/resolv.conf есть заглушка nameserver 127.0.0.53, значит, работает сервис systemd-resolve.

Конфигурация systemd-resolve находится в /run/systemd/resolve/resolv.conf. Статус systemd-resolve можно проверить командой

sudo resolvectl status

https://wiki.archlinux.org/title/Systemd-resolved

Пользовательские юниты

Непривилегированный пользователь тоже может запускать службы systemd от своего имени. Юнит-файлы нужно класть в ~/.config/systemd/user. Нюанс в том, что эти службы будут работать до тех пор, пока пользователь находится в системе. Если он выходит, то службы останавливаются. Чтобы службы работали вне зависимости от сеанса, нужно выполнить команду

loginctl enable-linger $USER
 
# Проверить, включена ли эта опция
loginctl user-status
...
  Linger: yes
 
# или показать только yes/no
loginctl show-user $USER -p Linger |cut -d= -f2

Пример unit-файла

[Unit]
Description=Minecraft Java server
 
[Service]
WorkingDirectory=/opt/minecraft
ExecStart=/usr/bin/java -Xmx1024M -Xms1024M -jar minecraft.jar nogui
Restart=on-failure
 
[Install]
WantedBy=multi-user.target

Управление службой такое же, нужно только добавлять параметр --user.

# После добавления юнита перечитать список демонов
systemctl --user daemon-reload

systemd-run

systemd-run позволяет превратить любую команду в фоновую задачу.

unitname=minecraft-server
systemd-run --user --unit=$unitname java -Xmx1024M -Xms1024M -jar minecraft.jar nogui
systemctl --user status $unitname
 
# Если вы ошиблись в команде или она завершилась с ошибкой
systemctl reset-failed

Удаление юнита

systemctl --user stop $unitname
find /run -name "*$unitname*" -exec rm -rf {} + 2> /dev/null
systemctl --user daemon-reload
systemctl --user reset-failed

https://superuser.com/questions/513159/how-to-remove-systemd-services

Поиск

systemctl --user list-units --all -t service --full --no-legend "$unitname.service" |xargs |cut -d' ' -f1

https://stackoverflow.com/questions/24398242/check-if-service-exists-in-bash-centos-and-ubuntu
https://stackoverflow.com/questions/369758/how-to-trim-whitespace-from-a-bash-variable

Таймер для периодического запуска

Сервис типа oneshot, запускающий скрипт

[Unit]
Description=Testlog service
#Wants=testlog.timer
 
[Service]
Type=oneshot
ExecStart=/home/user/testlog.sh
 
[Install]
WantedBy=multi-user.target

Таймер запуска каждые 3 минуты

[Unit]
Description=Testlog timer
#Requires=testlog.service
 
[Timer]
#Unit=testlog.service
OnCalendar=*:0/3
 
[Install]
WantedBy=timers.target

Использование таймеров systemd вместо заданий cron
https://www.freedesktop.org/software/systemd/man/latest/systemd.timer.html
https://www.digitalocean.com/community/tutorials/understanding-systemd-units-and-unit-files
https://unix.stackexchange.com/questions/126786/systemd-timer-every-15-minutes