Инструменты пользователя

Инструменты сайта


os:linux:systemd

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слеваПредыдущая версия
Следующая версия
Предыдущая версия
os:linux:systemd [13.09.2024 13:57] – [Зависимость между юнитами] viacheslavos:linux:systemd [30.04.2025 10:57] (текущий) – [Минимальный вариант] viacheslav
Строка 1: Строка 1:
 +====== systemd ======
 +https://www.freedesktop.org/software/systemd/man/index.html\\
 +[[https://www.redhat.com/sysadmin/systemd-automate-recovery|Set up self-healing services with systemd]]\\
 +[[https://www.youtube.com/watch?v=tY9GYsoxeLg|Demystifying Systemd]]\\
 +https://systemd-by-example.com/ - примеры с тестами в браузере.\\
 +https://systemd.io/\\
 +{{ :os:linux:s4a_latest.pdf |systemd для администраторов, русский перевод (Сергей Пташник, 28 октября 2017 г.)}}\\
 +[[https://habr.com/ru/companies/timeweb/articles/824146/|systemD с 0 до 1: библия сисадмина (Хабр)]]
 +===== Unit-файл =====
 +https://www.freedesktop.org/software/systemd/man/systemd.unit.html
 +
 +Это скрипт запуска приложения - как его запускать, под каким пользователем и т. д.
 +Системные юнит-файлы лежат в ''/lib/systemd/system'' (есть варианты), свои можно создавать в ''/etc/systemd/system''. Также в ''/etc/systemd/system'' находятся ссылки на системные юнит-файлы, эти ссылки делаются с помощью команды ''systemctl enable''.
 +После создания юнит-файла можно управлять запуском приложения - например, добавить в автозагрузку.
 +
 +Пример unit-файла:
 +<file bash /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
 +</file>
 +https://fedoramagazine.org/systemd-converting-sysvinit-scripts/
 +
 +<code bash>
 +man systemd.unit # Справка по юнитам
 +cat /proc/$(pidof cron)/environ # Вывести переменные процесса cron
 +journalctl -u cron.service -n 10 # Лог (последние 10 записей)
 +journalctl -u cron.service --since yesterday # Лог со вчерашнего дня
 +</code>
 +
 +Типы юнитов systemd
 +<code bash>
 +target # группирует модули
 +service # отвечает за запуск сервисов (служб) и поддерживает вызов интерпретаторов для исполнения пользовательских скриптов
 +mount # занимается монтированием файловых систем
 +automount # автомонтирование файловых систем, используется при обращении к точке монтирования
 +swap # отвечает за подключение файла подкачки
 +timer # запускает модули по расписанию, аналог cron
 +socket # запуск модуля при подключении к сокету
 +slice # группировка других модулей в контейнер (дерево) cgroups
 +device # использует реакцию на подключение какого-либо устройства
 +path # запуск модуля по событию доступа по конкретному пути в файловой системе
 +</code>
 +
 +Управление процессами systemd
 +<code bash>
 +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 # список установленных юнит-файлов сервисов
 +</code>
 +
 +==== Создать юнит ====
 +<code bash>
 +# Создание пользовательского сервиса и таймера (каталог ~/.config/systemd/user)
 +systemctl edit myservice --user --full --force
 +systemctl edit myservice.timer --user --full --force
 +
 +# Создание системного сервиса и таймера (каталог /etc/systemd/system), нужен рут
 +sudo systemctl edit myservice --full --force
 +sudo systemctl edit myservice.timer --full --force
 +</code>
 +После ''systemctl edit'' делать ''systemctl daemon-reload'' не нужно, в отличие от создания юнита как текстового файла в редакторе.
 +==== Зависимость между юнитами и порядок запуска ====
 +Перед запуском юнит может ''wants'' или ''requires'' другой юнит. Разница:
 +  * Если unit1 ''Wants=unit2'' и unit2 сбойнул, то это не влияет на запуск unit1.
 +  * Если unit1 ''Requires=unit2'' и unit2 сбойнул, то unit1 не запустится.
 +
 +Для чего нужен ''wants''? Например, в sshd.service есть ''Wants=sshd-keygen.service''. Sshd-keygen.service генерит ключи для сервера, если их нет. Если они есть, то sshd-keygen.service завершается с ошибкой, которая говорит о наличии ключей, но это не должно влиять на запуск sshd.service.
 +
 +''Wants'' и ''requires'' - это не порядок запуска, юниты запускаются вместе. За порядок запуска в systemd отвечают параметры ''Before'' и ''After''.
 +  * Если в unit1 есть параметр ''Before=unit2'', то unit1 запустится до unit2.
 +  * Если в unit1 есть параметр ''After=unit2'', то unit1 запустится после unit2.
 +
 +В примере sshd.service запустится только после того, как поднялась сеть и запустился sshd-keygen.
 +<code ini>
 +Wants=sshd-keygen.service
 +After=network.target sshd-keygen.service
 +</code>
 +
 +https://fedoramagazine.org/systemd-unit-dependencies-and-order/
 +
 +==== Target unit ====
 +Используется для связи и группировки других юнитов вместе, чтобы описать желаемое состояние системы. Некоторые из этих юнитов могут быть сервисами, некоторые - другими таргетами со своими группами юнитов.
 +
 +В примере нет выполняемой команды, таргет работает как связующее звено между другими таргетами.
 +<file ini 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
 +</file>
 +
 +  * ''multi-user.target'' требует (requires) успешного запуска ''basic.target''.
 +  * Если ''rescue.service'' или ''rescue.target'' запустились, то это останавливает юнит, и наоборот (conflicts).
 +  * Если ''multi-user.target'' запустится только после (after) ''basic.target'', либо ''rescue.service'' и ''rescue.target''.
 +
 +''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'' можно проверить командой
 +<code bash>
 +sudo resolvectl status
 +</code>
 +https://wiki.archlinux.org/title/Systemd-resolved
 +
 +
 +===== Пользовательские юниты =====
 +Непривилегированный пользователь тоже может запускать службы systemd от своего имени. Юнит-файлы нужно класть в ''~/.config/systemd/user''. Нюанс в том, что эти службы будут работать до тех пор, пока пользователь находится в системе. Если он выходит, то службы останавливаются. Чтобы службы работали вне зависимости от сеанса, нужно выполнить команду
 +<code bash>
 +loginctl enable-linger $USER
 +
 +# Проверить, включена ли эта опция
 +loginctl user-status
 +...
 +  Linger: yes
 +
 +# или показать только yes/no
 +loginctl show-user $USER -p Linger |cut -d= -f2
 +</code>
 +
 +Пример unit-файла
 +<code ini>
 +[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
 +</code>
 +
 +Управление службой такое же, нужно только добавлять  параметр ''%%--user%%''.
 +<code bash>
 +# После добавления юнита перечитать список демонов
 +systemctl --user daemon-reload
 +</code>
 +
 +===== systemd-run =====
 +systemd-run позволяет превратить любую команду в фоновую задачу.
 +<code bash>
 +unitname=minecraft-server
 +systemd-run --user --unit=$unitname java -Xmx1024M -Xms1024M -jar minecraft.jar nogui
 +systemctl --user status $unitname
 +
 +# Если вы ошиблись в команде или она завершилась с ошибкой
 +systemctl reset-failed
 +</code>
 +
 +Удаление юнита
 +<code bash>
 +systemctl --user stop $unitname
 +find /run -name "*$unitname*" -exec rm -rf {} + 2> /dev/null
 +systemctl --user daemon-reload
 +systemctl --user reset-failed
 +</code>
 +https://superuser.com/questions/513159/how-to-remove-systemd-services
 +
 +Поиск
 +<code bash>
 +systemctl --user list-units --all -t service --full --no-legend "$unitname.service" |xargs |cut -d' ' -f1
 +</code>
 +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
 +
 +Псевдосервис и получение его статуса для скриптов
 +<code bash>
 +systemd-run --user --unit=camunda sleep infinity
 +Running as unit: camunda.service
 +
 +systemctl --user is-active camunda.service
 +active # or inactive
 +</code>
 +===== systemd.timer =====
 +
 +Сервис типа oneshot, запускающий скрипт
 +<code ini>
 +[Unit]
 +Description=Testlog service
 +#Wants=testlog.timer
 +
 +[Service]
 +Type=oneshot
 +ExecStart=/home/user/testlog.sh
 +
 +[Install]
 +WantedBy=multi-user.target
 +</code>
 +
 +Таймер запуска каждые 3 минуты
 +<code ini>
 +[Unit]
 +Description=Testlog timer
 +#Requires=testlog.service
 +
 +[Timer]
 +#Unit=testlog.service
 +OnCalendar=*:0/3
 +
 +[Install]
 +WantedBy=timers.target
 +</code>
 +
 +[[https://habr.com/ru/companies/ruvds/articles/512868/|Использование таймеров 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\\
 +
 +Для работы нужно 3 компонента: скрипт, сервис systemd для запуска скрипта и таймер systemd для запуска сервиса.\\
 +Скрипт после создания нужно сделать исполняемым - ''chmod +x /scripts/test.sh''
 +
 +<code bash>
 +vi /etc/systemd/system/test.service
 +# Абсолютный минимум для сервиса:
 +[Service]
 +ExecStart=/scripts/test.sh
 +
 +# Вариант создания
 +systemctl edit --force --full test.service
 +# Вариант редактирования
 +systemctl edit --full test.service
 +
 +# Перечитать список сервисов (если редактировалось/создавалось с помощью systemctl edit, то не нужно)
 +sudo systemctl daemon-reload
 +# Можно запускать
 +systemctl start test.service
 +
 +# Логи сервиса test в реальном времени
 +sudo journalctl -u test -f
 +</code>
 +
 +Другие секции конфигурации сервиса
 +<code bash>
 +[Unit]
 +Description=This service runs the script /scripts/test.sh
 +
 +[Service]
 +ExecStart=/scripts/test.sh
 +User=worker # от имени кого будет работать
 +
 +# Если служба запускается по таймеру, секция [Install] не нужна
 +#[Install]
 +#WantedBy=multiuser.target # Если GUI нет
 +#WantedBy=graphical.target # Если это десктоп с GUI
 +</code>
 +
 +Таймер
 +<code bash>
 +# Кладётся в ту же папку, что и сервис
 +vi /etc/systemd/system/test.timer
 +
 +[Unit]
 +Description=This timer starts test.service
 +
 +[Timer]
 +Unit=test.service
 +# [DayOfWeek] Year-Month-Day Hour:Minute:Second
 +OnCalendar=*-*-* 20:15:00
 +Persistent=true # Если срабатывание пропущено, запустить при загрузке системы
 +#OnBootSec=5min # Через 5 мин после загрузки
 +
 +# Секция нужна для того, чтобы таймер можно было бы включить при загрузке системы
 +[Install]
 +WantedBy=timers.target
 +
 +# Перечитать сервисы
 +sudo systemctl daemon-reload
 +# Включить таймер при загрузке системы
 +sudo systemctl enable test.timer
 +
 +# Список таймеров
 +systemctl list-timers
 +</code>
 +[[https://www.youtube.com/watch?v=8640OcCL8T8|Linux Command Line (57) systemd.timer pt1 - MichaelsTechTutorials]]\\
 +[[https://www.youtube.com/watch?v=OV3Gc0SISUo|Linux Command Line (58) systemd.timer pt2 - MichaelsTechTutorials]]\\
 +[[https://habr.com/ru/post/535930/|Systemd для продолжающих. Part 1 — Запуск юнитов по временным событиям]]\\
 +[[https://www.freedesktop.org/software/systemd/man/latest/systemd.time.html|systemd.time — Time and date specifications]]
 +
 +==== Минимальный вариант ====
 +<code bash>
 +mkdir -p ~/.config/systemd/user
 +cd ~/.config/systemd/user
 +loginctl enable-linger $USER
 +
 +### cleanup.service
 +[Service]
 +ExecStart=/home/admin/scripts/cleanup.sh
 +
 +### cleanup.timer
 +# Секция [Install] нужна для автозагрузки таймера
 +[Timer]
 +OnCalendar=*-*-* 2:00:00
 +
 +[Install]
 +WantedBy=timers.target
 +
 +# Шебанг в скрипте обязателен, иначе сервис не поймёт, что именно он запускает
 +### /home/admin/scripts/cleanup.sh
 +#!/bin/bash
 +
 +find /opt/maven_repo/jjj -name 'business-application-*-1-DBI-*' -type f -mtime +5 -delete
 +find /opt/maven_repo/jjj -name 'business-model-*-1-DBI-*' -type f -mtime +10 -delete
 +find /opt/maven_repo/jjj/metamodel-* -name 'metamodel-*-1-DBI-*' -type f -mtime +5 -delete
 +
 +### Запуск, автозагрузка
 +systemctl --user daemon-reload
 +systemctl --user start cleanup.timer
 +systemctl --user enable cleanup.timer
 +</code>
 +
 +==== Срабатывание чаще минуты ====
 +
 +Например, раз в 10 сек
 +<code bash>
 +[Timer]
 +# Каждые 3 минуты
 +# OnCalendar=*:0/3
 +# Каждые 10 сек
 +OnCalendar=*:*:0/10
 +# Обязательный параметр для таймеров меньше минуты
 +AccuracySec=1s
 +
 +[Install]
 +WantedBy=timers.target
 +</code>
  

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki