systemd

Материал из llmdocs — справочник разработчика
systemd
Типсистема инициализации и менеджер служб
АвторыЛеннарт Поттеринг, Кай Сиверс
Первый выпуск2010
ЯзыкC
ЛицензияLGPL 2.1+
Основные утилитыsystemctl, journalctl, systemd-analyze, loginctl
По умолчанию вDebian, Ubuntu, Fedora, RHEL, Arch Linux, openSUSE
Сайтsystemd.io

systemd — система инициализации и менеджер служб для Linux. Ядро запускает её первым процессом (PID 1), и дальше systemd поднимает всё остальное: монтирует файловые системы, настраивает сеть, запускает службы, следит за ними и перезапускает при сбоях, а при выключении корректно всё останавливает. Помимо этого, в проект входят журнал (journald), управление сеансами пользователей (logind), сетевые настройки (networkd), DNS-резолвер (resolved), синхронизация времени и другие компоненты.

Почти все популярные дистрибутивы используют systemd по умолчанию, поэтому systemctl и journalctl — повседневные инструменты любого администратора.

История

Классическая система инициализации SysV init запускала службы shell-скриптами строго по очереди, не умела надёжно отслеживать упавшие процессы и медленно загружала систему. Ubuntu в 2006 году перешла на событийный Upstart, но в 2010 году Леннарт Поттеринг и Кай Сиверс из Red Hat предложили более радикальный подход в статье «Rethinking PID 1».[2]

Fedora 15 (2011) стала первым крупным дистрибутивом с systemd по умолчанию, затем последовали Arch Linux, openSUSE и RHEL 7. В 2014 году после долгого и бурного обсуждения на systemd перешёл Debian (выпуск Debian 8, 2015), а вслед за ним Ubuntu 15.04. Критики упрекали проект в нарушении философии Unix «одна программа — одна задача»; часть сообщества ушла в форки вроде Devuan, но большинство дистрибутивов осталось с systemd.

Юниты

Всё, чем управляет systemd, описывается юнитами (units) — текстовыми файлами в формате INI. Тип юнита задаётся расширением:

Тип Назначение
.service служба (демон или разовая задача)
.socket сокет; служба запускается при первом подключении
.timer запуск по расписанию — замена cron (см. cron и таймеры systemd)
.target группа юнитов, аналог уровней запуска (multi-user.target)
.mount, .automount точки монтирования
.path реакция на изменение файла

Системные юниты лежат в /usr/lib/systemd/system/ (от пакетов) и /etc/systemd/system/ (локальные, имеют приоритет). Зависимости задаются директивами Requires=, Wants=, After=, и systemd запускает независимые службы параллельно, что ускоряет загрузку.

Пример службы

# /etc/systemd/system/myapp.service
[Unit]
Description=My web app
After=network-online.target
Wants=network-online.target

[Service]
User=myapp
WorkingDirectory=/opt/myapp
EnvironmentFile=/etc/myapp.env
ExecStart=/opt/myapp/.venv/bin/uvicorn app:app --port 8000
Restart=on-failure
RestartSec=5

# песочница
NoNewPrivileges=yes
ProtectSystem=strict
ReadWritePaths=/var/lib/myapp
PrivateTmp=yes

[Install]
WantedBy=multi-user.target

Restart=on-failure перезапускает службу при падении, а параметры песочницы ограничивают её доступ к системе: запрещают повышение привилегий, делают файловую систему доступной только для чтения, кроме указанных путей.[3][5] Служба запускается от отдельного пользователя — см. Права доступа в Unix.

systemctl

sudo systemctl daemon-reload          # перечитать unit-файлы после изменений
sudo systemctl enable --now myapp     # включить автозапуск и запустить сразу
systemctl status myapp                # состояние, PID, последние строки лога
sudo systemctl restart myapp
systemctl list-units --failed         # что упало
systemctl list-timers                 # таймеры и время следующего запуска
systemctl cat myapp                   # итоговый unit-файл с переопределениями
sudo systemctl edit myapp             # переопределение без правки исходного файла
systemd-analyze blame                 # какие юниты дольше всего грузились

Команда systemctl edit создаёт файл-переопределение (drop-in) в /etc/systemd/system/myapp.service.d/, поэтому обновление пакета не затрёт локальные изменения.

Журнал

Компонент journald собирает вывод всех служб, сообщения ядра и syslog в единый структурированный журнал (см. journald и логи). Службе не нужно самой писать логи в файлы — достаточно выводить их в стандартный поток:[6]

journalctl -u myapp -f                 # следить за логом службы
journalctl -u myapp --since "1 hour ago"
journalctl -p err -b                   # только ошибки с момента загрузки

Таймеры

Таймер — пара юнитов name.timer и name.service. В отличие от cron, таймеры пишут вывод в журнал, учитывают зависимости, умеют догонять пропущенные запуски (Persistent=true) и добавлять случайную задержку, чтобы не нагружать сервер одновременно:[4]

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
RandomizedDelaySec=10m

systemd и контейнеры

Внутри Docker-контейнеров systemd обычно не запускают: контейнер содержит один процесс, а перезапуском занимается сам контейнерный рантайм или Kubernetes. На хосте же systemd управляет и демоном Docker, и cgroups, через которые ограничиваются ресурсы любых служб (MemoryMax=, CPUQuota=).[1]

См. также

Источники

  1. systemd.io — официальный сайт проекта
  2. Lennart Poettering — Rethinking PID 1 (2010)
  3. systemd.service — manual
  4. systemd.timer — manual
  5. systemd.exec — sandboxing options
  6. journalctl — manual