Добрый день дорогой читатель, данное повествование не является истиной в последней инстанции, это некая инструкция(хотя написана больше в справочном формате) по написанию Unit'ов для системы инициализации SystemD (в основном для собственного пользования) на Arch Linux с пояснениями и все возможными мыслями. Действия справедливы и к другим дистрибутивам на вышеупомянутой системе инициализации.
systemd - это система инициализации и менеджер сервисов для операционных систем на базе Linux, разработанная для управления процессами и службами в системе. Она была создана с целью замены традиционных систем инициализации, таких как SysVinit, и предлагает более современный и эффективный способ управления службами и ресурсами. Пробежимся по основным особенностям systemd
1. Параллельный запуск: systemd позволяет запускать службы параллельно, что значительно ускоряет процесс загрузки системы по сравнению с последовательным запуском, характерным для более старых систем.
2. Юниты: В systemd службы и другие ресурсы управляются через концепцию "юнитов" (units). Каждый юнит описывает сервис, сокет, таймер, целевой юнит или другой ресурс, и имеет свой файл конфигурации, который определяет его поведение. Вот это мы подробно разберем в этом повествовании.
3. Зависимости: systemd поддерживает управление зависимостями между юнитами. Это позволяет определять, какие службы должны быть активированы перед другими, а также управлять их порядком запуска и остановки.
4. Логирование: systemd включает в себя систему логирования journald, которая собирает и хранит журналы событий системы и служб. Это обеспечивает централизованное управление логами и упрощает их анализ. Кстати, думаю тоже коснуться этой темы, но это будет совсем другая история, так как в скользь я соприкосался в одной из статей.
5. Таймеры: Вместо использования cron для планирования задач, systemd предоставляет таймеры, которые могут быть использованы для запуска юнитов по расписанию.
6. Сокеты: systemd поддерживает сокетное активирование, что позволяет службам запускаться только по мере необходимости, когда поступает запрос на их использование. Это может помочь сократить использование ресурсов.
7. Состояние и управление: systemd предоставляет команды для управления состоянием юнитов, такие как start, stop, restart, enable, disable и другие. Это делает управление службами более удобным и интуитивно понятным.
8. Системные цели: systemd использует концепцию "целевых юнитов" (targets), которые представляют собой группы юнитов, позволяя управлять состоянием системы, например, переходить в многопользовательский режим или режим обслуживания.
Но довольно хвалебной оды, ее можно разводить бесконечно перечисляя ее компоненты и возможности, приступим к разбору.
unit в systemd — это основной объект конфигурации, описывающий службу, таймер, устройство, монтирование и другие системные ресурсы. Каждый unit представляет собой файл с расширением `.service`, `.socket`, `.mount` и т.п., который определяет параметры управления этим ресурсом.
Основные типы unit-файлов
- .service - системная служба (демон)
- .socket - сокет для активации служб
- .target - группа unit-ов (аналог runlevel)
- .mount - точка монтирования файловой системы
- .automount - автоматическое монтирование
- .timer - таймер для запуска заданий по расписанию
- .swap - swap-устройство
- .path - слежение за изменениями в файловой системе
- .slice - группа процессов (контроль ресурсов)
- .scope - группа процессов, созданных вне systemd
хранятся unit-файлы в следующих директориях:
- /usr/lib/systemd/system/ - системные unit-файлы (поставляются с пакетами)
- /etc/systemd/system/ - локальные (пользовательские) unit-файлы и переопределения
- ~/.config/systemd/user/ - пользовательские unit-файлы (для user-демонов)
Основные команды systemd для работы с unit
- systemctl start имя.service - запуск службы
- systemctl stop имя.service - остановка службы
- systemctl restart имя.service - перезапуск службы
- systemctl status имя.service - статус службы
- systemctl enable имя.service - включить автозапуск
- systemctl disable имя.service - отключить автозапуск
- systemctl list-units - список активных unit-ов
- systemctl cat имя.service - показать содержимое unit-файла
- systemd-analyze verify имя.service - проверить unit на ошибки
Основные секции unit-файла
[Unit] - общая информация и зависимости
[Service] - параметры службы (только для .service)
[Install] - параметры установки (для systemctl enable)
а теперь постараемся изучить каждую секцию более подробно
Секция [Unit]
Секция [Unit] содержит общую информацию и зависимости, в свою очередь секция может содержать следующие директивы:
Description= - Краткое описание юнита. Используется для удобства и отображается в статусе.
Например: Description=My custom service
Documentation= - Ссылки на документацию (URL, man-страницы, локальные файлы). Можно указать несколько значений через пробел.
Например: Documentation=man:myapp(8) https://example.com/myapp/docs
Requires= - Жёсткие зависимости, юнит не запустится, если указанные юниты не активны. Если юнит из Requires не запущен, systemd попытается его запустить.
Например: Requires=network.target
Wants= - Желательные зависимости, systemd попытается запустить указанные юниты, но не будет считать это ошибкой, если они не запустились.
Например: Wants=network-online.target
After= - Указывает порядок запуска, данный юнит запускается после указанных. Не означает зависимость, только порядок.
Например: After=network.target
Before= - Противоположно After= данный юнит запускается до указанных.
Например: Before=shutdown.target
Conflicts= - Юниты, которые конфликтуют с данным — при старте этого юнита conflicting-юниты будут остановлены.
Например: Conflicts=shutdown.target
OnFailure= - Юниты, которые будут запущены в случае неудачи данного юнита.
Например: OnFailure=notify-admin.service
PartOf= - Указывает, что данный юнит является "частью" другого юнита (родительского). Если родительский юнит останавливается, перезапускается или изменяет состояние, это может распространиться на дочерние юниты, включая остановку или перезапуск. Полезно для связанных сервисов, например, если у вас есть основной сервис и вспомогательные (например, сокет или таймер), которые должны следовать за основным.
Например: PartOf=my-main.service
Если `my-main.service` остановлен, этот юнит также будет остановлен автоматически. Это не жёсткая зависимость (как Requires=), а скорее правило поведения при событиях.
PropagationBlocking= - Блокирует распространение определённых событий (например, остановки, перезапуска или сбоя) от этого юнита к другим юнитам, которые зависят от него. Это предотвращает каскадные эффекты, такие как автоматическая остановка зависимых юнитов при проблемах с этим. В сценариях, где нужно изолировать юнит от влияния на другие, например, для критических сервисов или при отладке, чтобы избежать нежелательных остановок.
Например: PropagationBlocking=yes
Если этот юнит столкнётся с ошибкой, он не будет автоматически останавливать юниты, которые зависят от него (например, через Wants= или Requires=). Этот параметр появился в более поздних версиях systemd (начиная с версии 256). В старых версиях может не поддерживаться. По умолчанию no.
DefaultDependencies= - Определяет, добавляет ли systemd стандартные (по умолчанию) зависимости автоматически. Если yes (по умолчанию для большинства юнитов), systemd добавляет зависимости вроде After=basic.target, Requires=sysinit.target и другие, чтобы обеспечить правильный порядок загрузки. Если no, все зависимости нужно задавать вручную. Отключите (no), если хотите полный контроль над зависимостями (например, для специальных юнитов или в контейнерах). Включите (yes), чтобы использовать стандартные зависимости для совместимости. Например: DefaultDependencies=no
В этом случае юнит не получит автоматические зависимости, и вы должны явно указать After=, Requires= и т.д., если нужно. Для некоторых типов юнитов (например, .target), значение по умолчанию может отличаться. Всегда проверяйте с помощью systemctl show <unit>.
Condition...= например, ConditionPathExists=, ConditionUser =, и другие условия, при которых юнит будет запущен. Если условие не выполняется, юнит не запустится. Часто используется для проверки окружения.
Например: ConditionPathExists=/etc/myapp/config
Assert...= например, AssertPathExists=, AssertUser =, и другие, аналогично Condition, но если условие не выполняется — запуск юнита считается ошибкой.
Например: AssertUser=root
RefuseManualStart= - Запрещает запуск юнита вручную через systemctl start`. Принимает значения yes или no (по умолчанию no).
Например: RefuseManualStart=yes
RefuseManualStop= - Запрещает остановку юнита вручную через systemctl stop.
Например: RefuseManualStop=yes
IgnoreOnIsolate= - Если yes, юнит не будет остановлен при переходе в другой изолятор (target).
Например: IgnoreOnIsolate=yes
JobTimeoutSec= - Таймаут для выполнения задачи systemd с этим юнитом. Если превышен, задача прерывается.
Например: JobTimeoutSec=30s
JobTimeoutAction= - Действие при превышении таймаута, например: fail, stop, ignore.
Например: JobTimeoutAction=stop
StartLimitIntervalSec= и StartLimitBurst= - Параметры ограничения частоты перезапуска юнита.
- StartLimitIntervalSec - интервал времени.
- StartLimitBurst - максимальное число запусков за интервал.
Например: StartLimitIntervalSec=60 StartLimitBurst=5
в данной секции не все директивы вам портебуются, но все же старался максимально все директивы рассмотреть в краце.
Секция [Service]
Секция [Service] в unit-файле описывает параметры запуска и поведения конкретного сервиса (демона). Это ключевая часть unit-файла типа .service (в unit-файле .timer секция [Timer], в .socket секция [Socker] и так далее но там немного другие директивы), которая определяет, как systemd должен запускать, контролировать и останавливать процесс. Может содержать следующие директивы:
Type= - тип процесса (simple, forking, oneshot, notify, dbus, idle) Тип процесса, определяющий, как systemd понимает, что сервис запущен.
- simple - systemd считает сервис запущенным сразу после запуска команды ExecStart. Подходит для простых демонов, которые не форкаются.
- forking - сервис форкается в фоне, systemd ждёт, пока родительский процесс завершится, чтобы считать сервис запущенным. Часто используется для классических демонов.
- oneshot - для однократных задач (например, скриптов инициализации). systemd ждёт завершения процесса.
- notify - сервис сообщает systemd о готовности через sd_notify.
- dbus - systemd ждёт регистрации сервиса в D-Bus.
- idle - запуск отложен до освобождения ресурсов.
ExecStart= - Команда, которая запускает сервис. Обязательный параметр.
Например: ExecStart=/usr/bin/mydaemon --flag
ExecStartPre= Команды, выполняемые перед основным запуском (можно несколько).
Например: ExecStartPre=/bin/echo "Start service"
ExecStartPost= - Команды, выполняемые после основного запуска. Например: ExecStartPost=/bin/echo "Started"
ExecStop= - Команда для остановки сервиса. Если не указана, systemd отправит SIGTERM основному процессу.
Например: ExecStop=/bin/kill -TERM $MAINPID
ExecStopPost= - команды после остановки
Например: ExecStopPost=/bin/echo "Stoped service"
ExecReload= - Команда для перезагрузки сервиса (например, reload конфигурации).
Например: ExecReload=/bin/kill -HUP $MAINPID
Restart= - Политика перезапуска сервиса при сбоях. может принимать следующие значения:
- no - (по умолчанию): Сервис не перезапускается автоматически.
- on-success - Перезапуск только если сервис завершился успешно (exit code 0).
- on-failure - Перезапуск при неудачном завершении (неуспешный exit code, сигнал или таймаут).
- on-abnormal - Перезапуск при аварийном завершении (сигналы SIGTERM, SIGINT, SIGHUP, SIGPIPE, таймаут или сбой).
- always - Перезапуск всегда, независимо от причины остановки (кроме ручной остановки через `systemctl stop`).
- on-abort - Перезапуск только при получении сигнала SIGABRT.
- on-watchdog - Перезапуск при срабатывании watchdog-таймера (если настроен `WatchdogSec`).
RestartSec= - задержка перед перезапуском
Например RestartSec=5s
TimeoutStartSec= - Время ожидания запуска сервиса перед ошибкой.
Например: TimeoutStartSec=30s
TimeoutStopSec= - Время ожидания остановки сервиса. Например: TimeoutStopSec=30s
PIDFile= - Путь к файлу с PID, если сервис форкается (Type=forking) и пишет PID в файл.
Например: PIDFile=/run/mydaemon.pid
User= - Пользователь, от имени которого запускается сервис.
Например: User =jodi
Group= - Группа, от имени которой запускается сервис. Например: Group=webdevops
WorkingDirectory= - Рабочая директория для сервиса.
Например: WorkingDirectory=/var/lib/myapp
Environment= - Переменные окружения, доступные сервису.
Например: Environment=VAR=value
EnvironmentFile= - файл с переменными окружения доступные сервису.
Например: EnvironmentFile=/opt/myservice/env
RemainAfterExit= - Для Type=oneshot считать сервис активным после выхода процесса.
Например: RemainAfterExit=yes
StandardOutput= - Направление stdout сервиса (journal, syslog, null, tty, file:path).
Например: StandardOutput=null
StandardError= - Направление stderr сервиса.
Например: StandardError=journal
Так же имеются директивы ограничения ресурсов и директивы безопасности.
LimitNOFILE= - Максимальное количество открытых файловых дескрипторов (file descriptors) для процесса. Чтобы ограничить, сколько одновременно файлов, сокетов и пр. может открыть процесс. Помогает избежать исчерпания ресурсов. Значение целое число (или `infinity`).
LimitNPROC= - Максимальное количество процессов/потоков, которые может создать сервис. Ограничивает форк новых процессов, предотвращая fork-бомбы и избыточное потребление ресурсов.
Например: LimitNPROC=512
PrivateTmp= - Использовать отдельный временный каталог `/tmp` и `/var/tmp` для сервиса. Изолирует временные файлы сервиса от остальных процессов, повышая безопасность и предотвращая конфликты. Принимает значения yes /no
Например:PrivateTmp=yes
ProtectHome= - Защищает домашние директории `/home`, `/root` и `/run/user` от записи или полностью маскирует. Защита приватных данных пользователя от изменения или чтения сервисом.
- no - без защиты (по умолчанию).
- read-only - делает домашние директории только для чтения.
- yes - маскирует домашние директории (делает недоступными).
Например: ProtectHome=read-only
ProtectSystem= - Ограничивает доступ к системным директориям. Предотвращает изменение системных файлов сервисом.
- no - без ограничения.
- yes - делает `/usr`, `/boot`, `/etc` только для чтения.
- strict - делает их только для чтения и маскирует все остальные кроме `/etc` и `/usr`.
- full - делает `/usr`, `/boot`, `/etc` и `/var` только для чтения.
Например: ProtectSystem=strict
ReadOnlyPaths= - Монтирует указанные пути в режиме «только для чтения». Позволяет гибко ограничить запись на конкретные каталоги. Значение, Список путей, разделённых пробелами.
Например: ReadOnlyPaths=/etc /usr/bin
AmbientCapabilities= - Дополнительные Linux capabilities, которые будут добавлены в окружение сервиса.Позволяет сервису выполнять операции, требующие повышенных прав, без запуска от root. Значения список capability, например CAP_NET_BIND_SERVICE CAP_SYS_TIME.
Например: AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet= - Ограничивает набор Linux capabilities, доступных сервису и его потомкам. Уменьшает права сервиса, ограничивая возможности ядра, повышая безопасность. Значение Список capabilities, или `CAP_SYS_ADMIN` и т.п.
Например: CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_CHOWN
NoNewPrivileges= - Запретить процессу и его потомкам получать новые привилегии (например, через setuid, capabilities). Предотвращает повышение привилегий в ходе работы сервиса, повышая безопасность. Значения принимает yes/no
Например: NoNewPrivileges=yes
Опять же повторюсь не все директивы вам портебуются для написания сервиса, но все же в краце их стоит рассмотреть для понимания какой масштаб возможностей предоставляет systemd для управления сервисами
Секция [Install]
Секция [Install] в файлах systemd unit (таких как `.service`, `.timer`, `.socket` и др.) определяет, как юнит интегрируется в систему при его "включении" (enable) через systemctl enable. Она не влияет на работу юнита, но управляет его активацией и зависимостями. Вот основные директивы, которые могут быть в этой секции.
WantedBy= - Указывает юнит(ы), которые "хотят" этот юнит, т.е. он будет запущен, когда указанный юнит достигает состояния "активен". Чаще всего используется для служб.
Например: WantedBy=multi-user.target - служба запустится при входе в многопользовательский режим.
RequiredBy= - Аналогично `WantedBy=`, но указывает, что этот юнит "требуется" другими юнитами. Если он не может запуститься, это может заблокировать зависимые юниты.
Например: RequiredBy=network.target - юнит обязателен для сетевого таргета.
Also= - Перечисляет дополнительные юниты, которые должны быть установлены (enable) вместе с этим. Полезно для связанных компонентов.
Например: Also=my-service.socket - при включении службы также включится её сокет.
Alias= - Создаёт псевдонимы (алиасы) для юнита, позволяя обращаться к нему по другим именам.
Например: Alias=my-app.service - юнит можно будет запустить как my-app.service.
DefaultInstance= - Для шаблонных юнитов (с @ в имени) задаёт экземпляр по умолчанию.
Например: DefaultInstance=foo - для юнита template@.service по умолчанию будет template@foo.service.
Эти директивы не обязательны - секция [Install] может отсутствовать, если юнит не предназначен для "включения". После изменения unit файла нужно перезагрузить конфигурацию командой: systemctl daemon-reload. Если юнит - не служба (например, .target), некоторые директивы могут не применяться.
и так давайте все же посмотрим Unit'ы для начала возьмем пользовательские что бы посмотреть какие есть введем команду:
ls /etc/systemd/system/*.service
остальные Unit'ы пока не будем рассматривать, только демоны (.service)
Рассмотрим юнит syncthing, внутри три секции все по стандарту [Unit] [Service] и [Install]. Пробежимся по [Unit] все давольно таки тривиально
Description=Syncthing - Open Source Continuous File Synchronization for %I Содержит краткое описание
Documentation=man:syncthing(1) Содержит ссылку на man по данному софту
а далее уже интереснее
After=network.target данный параметр говорит нам что наш юнит syncthing будет запускаться после юнита network.target который в свою очередь затрагивает запуск группы юнитов входящих в network.target
Wants=syncthing-inotify@.service желательная зависимость в демоне, syncthing-inotify@.service, systemd попытается запустить syncthing-inotify@.service, но не будет считать это ошибкой, если они не запустся. Юнит syncthing продолжет запуск в штатном режиме
и самое интересное секция [Service]
User=%i Пользователь, от имени которого запускается syncthing в данном случае он берется из %i, а передается через команду запуска это выглядит так systemctl restart syncthing@john.service
ExecStart=/usr/bin/syncthing serve --logfile=null путь до утилиты с ее параметрами для запуска
Restart=on-failure Политика перезапуска, syncthing перезапускается при неудачном завершении
SuccessExitStatus=3 4 в данном параметре определяет, что коды 3 и 4 выхода (exit codes) процесса считаются успешными. Иначе по умолчанию
systemd считает успешным только код 0, а остальные ошибками, что может привести к перезапуску службы или другим действиям. При этом Restart=on-failure будет игнорировать ошибки, 3 и 4 Перезапуск произойдет только при "настоящих" ошибках
RestartForceExitStatus=3 4 означает, что при выходе с кодом 3 или 4 syncthing будет перезапущен немедленно, игнорируя стандартную логику Restart.(???)
И конечно же секция [Install] отвечает по сути за использование команд с Enable/Disable
WantedBy=multi-user.target говорит что syncthing запустится при входе в многопользовательский режим, multi-user.target который в свою очередь затрагивает запуск группы юнитов входящих в multi-user.target
этих параметров будет достаточно для запуска юнита syncthing
давайте еще посмотрим юнит например балансировка btrfs, как видим секция [Install] отсутствует а значит вероятнее всего запускается по требованию либо же через таймер.
и так в секции [Unit] видим привычные строки, но все же обратим внимание на третий параметр
After=fstrim.service btrfs-trim.service btrfs-scrub.service что говорит об очередности запуска нашего юнита, сперва будут запущены fstrim.service btrfs-trim.service btrfs-scrub.service а потом уже btrfs-balance.service, думаю уже более понятнее стало.
переходим к [Service] уже давольно таки понятно
Type=simple говорит о том что юнит btrfs-balance.service будет считатся запущеным после выполнения команды запуска скрипта то бишь кторая ниже
ExecStart=/usr/share/btrfsmaintenance/btrfs-balance.sh тут все ясно и без коментариев, используется абсолютный путь для скрипта с действиями
IOSchedulingClass=idle Устанавлен класс планировщика ввода-вывода
(I/O scheduler class) для процессов службы. Значение idle означает, что I/O операции (чтение/запись на диск) выполняются только когда система I/O простаивает, не конкурируя с другими процессами.
CPUSchedulingPolicy=idle Устанавлена политика планирования CPU для процессов службы. Значение idle означает, что процесс получает CPU только когда система простаивает (низкий приоритет), не мешая другим задачам.
перейдем к системным unit'ам их можно увидеть выполнив следующую команду
ls /usr/lib/systemd/system/*.service
их довольно таки много, опять же в контесте повествования рассматриваем демонов (.service)
на пример из простого iptables довольно простой
секция [Unit] все давольно таки знакомо
Description=IPv4 Packet Filtering Framework описание юнита
Before=network-pre.target данный параметр говорит что iptables должен запуститься раньше юнита network-pre.target
Wants=network-pre.target эта зависимоть говорит нам о том что желательно был запущен network-pre.target, если он не запущен или systemd не сможет это стделать то не будет считаться ошибкой и iptables запустится штатно
секция [Service]
Type=oneshot используется для однократных задач (например, скриптов инициализации). systemd ждёт завершения процесса.
ExecStart=/usr/bin/iptables-restore /etc/iptables/iptables.rules скрипт для запуска iptables c конфигом правил
ExecReload=/usr/bin/iptables-restore /etc/iptables/iptables.rules аналогично выше сказанному
ExecStop=/usr/lib/systemd/scripts/iptables-flush аналогично, выполняется скрипт остановки
RemainAfterExit=yes используется вмесет с Type=oneshot считать сервис активным после выхода процесса.
секция [Install]
WantedBy=multi-user.target говорит что iptables запустится при входе в многопользовательский режим. multi-user.target который в свою очередь затрагивает запуск группы юнитов входящих в multi-user.target
Разберем юнит docker начнем как обычно с секции [Unit] первые два параметра нам уже знакомы краткое описание юнита и ссылка на документацию
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
вот тут уже по интереснее
After=network-online.target nss-lookup.target docker.socket firewalld.service containerd.service time-set.target первым делом будут запущены юниты в списке и те что в группе юнитов списка
Wants=network-online.target containerd.service этот параметр говорит нам о том что желательно бы были запущены следующие юниты, даже если systemd не сможет запустить их это не будет считаться ошибкой и юнит продолжит работы
Requires=docker.socket в этом параметре видим, данный юнит доллжен быть запущен, если нет то systemd попытается его запустить и если не сможет то запуск docker.service завершится ошибкой
StartLimitBurst=3 максимальное число попыток запуска юнита за интервал времени указаный в параметре ниже
StartLimitIntervalSec=60 интервал времени для попыток запуска юнита
Перейдем к секции [Service] там весьма интересно
Type=notify сервис сообщает systemd о готовности через sd_notify.
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock команда для запуска демона
ExecReload=/bin/kill -s HUP $MAINPID командна для перезапуска
TimeoutStartSec=0 сколько секунд ждать перед запуском
RestartSec=2 перезапуск через 2 секунды
Restart=always Схема перезапуска, всегда перезапуск, независимо от причины остановки (кроме ручной остановки через systemctl stop).
LimitNPROC=infinity Ограничивает максимальное количество процессов (включая потоки/threads) для службы. Если служба попытается создать больше, systemd убьет ее. Это предотвращает "вилочные бомбы" (fork bombs) или неконтролируемый рост процессов. В данном случае установлено без ограничений.
LimitCORE=infinity Ограничивает размер core dump файлов (дампы памяти для отладки при крахе процесса). Если размер превышен, дамп обрезается или не создается. Полезно для экономии места на диске и предотвращения переполнения. В данном случае установлено без ограничений.
TasksMax=infinity В отличие от старого LimitNPROC, TasksMax работает на уровне cgroups и учитывает все задачи, включая потоки. По умолчанию — неограничено, но можно задать лимит (например, 1000). infinity эквивалентно снятию лимита.
Delegate=yes параметр который делегирует управление cgroups (control groups) для службы. Если Delegate=yes, служба получает полный контроль над своими subcgroups, позволяя ей создавать и управлять дочерними группами ресурсов. Это полезно для контейнеров или сервисов, которые запускают другие процессы. По умолчанию Delegate=no, и служба не может создавать subcgroups. С yes она может, что дает больше гибкости, но требует осторожности, чтобы не нарушить изоляцию.
KillMode=process параметр, который определяет стратегию завершения процессов при остановке службы. В данном случае означает, что systemd убивает только основной процесс (PID), но не затрагивает дочерние процессы, они могут завершиться самостоятельно или быть убиты позже.
OOMScoreAdjust=-500 это параметр настраивает приоритет процесса для OOM Killer'а (Out-of-Memory killer) в Linux. Значение -500 делает процесс
менее вероятным для убийства при нехватке памяти — чем ниже, тем выше
приоритет (защита от OOM). Диапазон от -1000 (максимальная защита) до 1000 (максимальный риск). По умолчанию - 0. OOM Killer использует это для расчёта oom_score (/proc/[pid]/oom_score). -500 хорошая защита для критических служб, но не абсолютная.
секция [Install] достаточно тривиальна
WantedBy=multi-user.target говорит что docker запустится при входе в многопользовательский режим. multi-user.target который в свою очередь затрагивает запуск группы юнитов входящих в multi-user.target
Хочу подвести итоги данного повествования, systemd это мощьный и достаточно сложный и требующий более длительного времени на изучение инструмент по управленению процессами системы на базе Linux, в данном случае коснулись общего поняти создания Unit'ов в основном сервисов(.service), в дальнейшем по мере изучения systemd постараюсь описать структуру других Unit'ов.
За сим откланиваюсь...