systemd¶
systemd - PID 1, то есть первый процесс, который запускает ядро Linux. Он поднимает всю остальную систему и дальше управляет ею. Вокруг PID 1 выросло целое семейство системной обвязки: журнал, управление устройствами, сессиями пользователей, сетью, DNS, временем, загрузчиком.
Note
Отсюда главная путаница в спорах. «systemd» называют то init-систему (один бинарник), то весь проект из десятков компонентов - фактически новый слой «Linux userspace plumbing» между ядром и приложениями.
Название - игра слов: d - стандартный суффикс демонов (sshd, httpd), а Système D - французское выражение
про умение выкрутиться в любой ситуации.
Предыстория: init до systemd¶
SysV init (1983-2010)¶
В Linux пришла модель из UNIX System V (AT&T, 1983). Linux-реализацию sysvinit написал Миквел ван Смуренбург в 1992 году.
/etc/inittabи runlevels: 0 - выключение, 3 - многопользовательский режим, 5 - графика, 6 - перезагрузка/etc/init.d/- shell-скрипты с аргументамиstart | stop | restart | status/etc/rc3.d/- ссылки на них видаS20network,S80nginx, номер в имени задаёт порядок запуска
Двадцать лет это работало, но к концу 2000-х проблемы стали очевидны:
- Всё последовательно. Сервис 80 ждёт сервис 20, даже если они никак не связаны. На ноутбуках загрузка занимала минуты.
- Init не знает, что с сервисом. Скрипт запустил демона, тот ушёл в фон (
fork+daemonize), PID записан в/var/run/x.pid. Демон упал - никто не поднимет, а PID-файл врёт. - Нельзя надёжно убить сервис со всеми потомками. Демон, который форкнул десять процессов, после
stopоставлял сирот. - Сотни строк shell на каждый сервис, у каждого дистрибутива свои:
functionsв Red Hat,lsb-baseв Debian. - Мир стал динамическим: USB, Wi-Fi, ноутбуки, сон и пробуждение, горячее подключение дисков. Модель «загрузились по списку и всё» под это не подходила.
Кто пытался раньше¶
- daemontools (Дэниел Бернстайн, 1990-е) → runit (2004) → s6 - идея супервизии: сервис работает на переднем плане, родитель-надзиратель видит его смерть и перезапускает. Минималистично и надёжно, но в мейнстрим не вышло
- launchd от Apple (Mac OS X 10.4, 2005) - первым показал socket activation и запуск по требованию. Поттеринг позже прямо называл его источником идей
- SMF в Solaris 10 (2005) - сервисы с зависимостями и манифестами
- Upstart от Canonical (Скотт Джеймс Ремнант, Ubuntu 6.10, 2006) - первая серьёзная замена SysV в Linux. Событийная модель: «когда случилось событие X, запусти Y». Его взяли Ubuntu, Fedora 9-14, RHEL 6 и Chrome OS
Слабое место Upstart. Событийная модель идёт снизу вверх: администратор описывает цепочку событий, которая приведёт к запуску нужного сервиса. Естественнее сверху вниз -- «я хочу это, ему нужно вот то», а цепочку пусть выводит система. Плюс CLA от Canonical: чтобы закоммитить, нужно было передать права на код компании, и внешним разработчикам это не нравилось.
Рождение: «Rethinking PID 1» (2010)¶
30 апреля 2010 года Леннарт Поттеринг опубликовал пост «Rethinking PID 1» с экспериментальной системой. Делали её вдвоём с Каем Зиверсом, мейнтейнером udev. Оба работали в Red Hat. У Поттеринга к тому моменту была громкая и неоднозначная репутация автора PulseAudio и Avahi.
Идеи поста, которые определили всё дальнейшее:
- Запускать меньше и параллельнее. Не запускать то, что не нужно сейчас, а нужное - одновременно.
- Socket activation - главный трюк. Сервис B ждёт сервис A потому, что хочет подключиться к его сокету.
Значит, init может сам заранее создать все сокеты (
/dev/log,/run/dbus/system_bus_socket) и запустить A и B одновременно. Если B напишет в сокет раньше, чем A готов, ядро подержит данные в буфере. Порядок зависимостей перестаёт тормозить загрузку. - Трекинг процессов через cgroups. Каждый сервис в своей control group ядра: init точно знает, какие процессы его, даже после десятка форков, и может убить их все. PID-файлы не нужны.
- Меньше shell. Вместо скриптов - декларативные unit-файлы в стиле
.ini. Типовые задачи (монтирование, hostname, загрузка модулей) переписаны на C внутри init. - Зависимости вместо событий. Описываешь, что нужно (
Requires=,Wants=) и в каком порядке (After=), а граф система выводит сама.
Мейнтейнер Upstart Ремнант ответил на пост в тот же день. Так началось противостояние на пять лет.
Почему Red Hat¶
systemd не начинался как корпоративный проект «по приказу сверху». Его начали два инженера Red Hat, недовольные Upstart, практически по своей инициативе. Red Hat быстро увидел, что он решает его собственные задачи, и стал вкладываться:
- Быстрая и предсказуемая загрузка Fedora и RHEL - на серверах и на ноутбуках разработчиков.
- Надёжная супервизия для энтерпрайза. Упавший сервис поднять, при остановке убить все процессы. Для поддержки RHEL это прямые деньги: меньше тикетов «процесс висит после stop».
- Единый интерфейс администрирования.
systemctl restart nginxиjournalctl -u nginxодинаковы в любом дистрибутиве. Обучение и поддержка дешевеют, а крупнейший коммерческий игрок от стандартизации выигрывает больше всех. - Контроль над критическим слоем. Upstart принадлежал Canonical и требовал CLA. Держать ключевой компонент своей ОС в руках конкурента Red Hat не хотел.
- cgroups и изоляция - фундамент будущих контейнеров. Red Hat рано сделал ставку на контейнеры (OpenShift, Podman), и init, который нативно управляет cgroups, лёг в эту стратегию.
Note
Миф «Red Hat захватывает Linux» в войнах за init звучал громко. Red Hat действительно получил огромное влияние на userspace Linux. Но systemd приняли технические комитеты независимых дистрибутивов (Arch, Debian, SUSE, затем Ubuntu), в основном по техническим причинам.
Хронология¶
| Год | Событие | Почему важно |
|---|---|---|
| 2010 | Пост «Rethinking PID 1» | Рождение проекта |
| 2011 | Fedora 15 - первый крупный дистрибутив с systemd по умолчанию. Тогда же openSUSE 12.1 | Обкатка в реальном мире |
| 2012 | udev влит в репозиторий systemd | Первый сигнал «systemd - не только init». Gentoo отвечает форком eudev |
| 2012 | Arch Linux переходит на systemd | Самосборщики приняли - сильный сигнал |
| 2012-2013 | logind заменяет заброшенный ConsoleKit. GNOME 3.8 бросает ConsoleKit, позже части GNOME требуют logind | Рабочий стол начинает зависеть от systemd: «навязывают через GNOME» |
| 2013 | Предсказуемые имена интерфейсов: enp3s0 вместо eth0 |
Конец гонок «какая сетевуха стала eth0 после ребута» |
| 2014 | RHEL 7 и SLES 12 выходят с systemd | Энтерпрайз принял, вопрос де-факто решён |
| февраль 2014 | Технический комитет Debian: 4 на 4 между systemd и Upstart, ничью решает председатель Бдейл Гарби в пользу systemd | Главная развилка истории |
| 2014 | Через несколько дней Canonical объявляет переход Ubuntu | Upstart фактически мёртв |
| апрель 2014 | Торвальдс отказывается принимать патчи ядра от Кая Зиверса | Пик конфликта ядра и systemd |
| ноябрь 2014 | Общее голосование Debian (GR) о запрете жёстких зависимостей от одного init проваливается | Решение комитета остаётся в силе |
| 2014 | Объявлен Devuan - форк Debian без systemd | Раскол становится организационным |
| 2015 | Debian 8 Jessie и Ubuntu 15.04 с systemd | Почти весь мейнстрим на systemd |
| 2015 | kdbus (D-Bus в ядре от команды systemd) не принимают | Позже появляется userspace-замена dbus-broker |
| 2016 | KillUserProcesses=yes по умолчанию (v230): выход из сессии убивает tmux и screen |
Новый виток ненависти, дистрибутивы меняют дефолт |
| 2017 | Devuan 1.0 | Альтернатива доведена до релиза |
| 2019 | Fedora 31 включает cgroups v2 по умолчанию - первой из крупных | systemd тянет за собой контейнерную индустрию |
| 2020 | systemd-homed (v246), systemd-oomd (v247) | Экспансия в домашние каталоги и управление памятью |
| 2022 | Поттеринг уходит из Red Hat в Microsoft. Основана UAPI Group - сообщество спецификаций userspace | systemd становится межкорпоративным, стандарты выносятся отдельно |
| 2024 | Бэкдор в xz - путь в sshd шёл через libsystemd | Урок о связанности |
| 2024 | run0 (v256) - замена sudo без SUID-бита |
systemd замахнулся даже на sudo |
| 2025 | v258 удаляет cgroups v1, v259 - экспериментальная поддержка musl | Наследие отрезается, systemd приходит в Alpine и postmarketOS |
| январь 2026 | Поттеринг уходит из Microsoft и с Крисом Кюлем и Кристианом Браунером основывает Amutable - компанию про верифицируемую целостность Linux | Следующий фронт - доверенная загрузка |
| март 2026 | v260 окончательно удаляет поддержку SysV init-скриптов | Мост в прошлое сожжён через 16 лет. Дальше вышла v261 |
Войны за init¶
Голосование Debian, 2014. Многомесячные споры, сотни писем, отставки. Технический комитет разделился поровну, решил голос председателя. Иэн Джексон, сторонник свободы выбора init, после этого ушёл из комитета. Debian - база для Ubuntu, Mint и сотен других дистрибутивов, поэтому решение определило судьбу всей экосистемы.
Торвальдс против Зиверса, 2014. systemd начал реагировать на параметр ядра debug и заваливал логами консоль
так, что система переставала нормально грузиться. Разработчики ядра попросили исправить, Зиверс ответил в духе
«debug - общий параметр, не только ядра» и закрыл баг. Торвальдс публично отказался принимать от Зиверса патчи
(тот как раз продвигал kdbus), пока тот не начнёт исправлять ломающее других поведение. Конфликт стал символом
претензии «systemd не уважает чужие границы».
Devuan и «Veteran Unix Admins». Группа администраторов форкнула Debian под лозунгом свободы выбора init. Devuan жив до сих пор, но остался нишевым.
Бэкдор в xz, 2024 - самый поучительный эпизод.
- OpenSSH сам от systemd не зависит. Но Debian и Fedora патчили sshd, чтобы тот сообщал systemd о готовности
через
sd_notify. - Для этого sshd линковался с libsystemd, а libsystemd - с liblzma (сжатие журнала).
- Атакующий через многолетнюю социальную инженерию стал мейнтейнером xz и встроил в liblzma бэкдор, который по этой цепочке оказывался в процессе sshd.
Последствия:
- systemd перевёл тяжёлые зависимости libsystemd на загрузку по требованию через
dlopen - протокол
sd_notifyстали рекомендовать реализовывать самим - это 10-20 строк на C без всей библиотеки - в самом systemd дыры не было, но эпизод наглядно показал главный довод критиков: большая связанная поверхность повышает цену любой компрометации
Влияние на индустрию¶
Даже противники признают: systemd изменил Linux сильнее любого userspace-проекта за последние 20 лет.
- Один способ администрировать любой дистрибутив.
systemctl,journalctl,hostnamectl,timedatectl,localectlодинаковы в Fedora, Debian, Arch, SUSE. Unit-файл от вендора софта работает везде, а раньше каждый пакет тащил init-скрипты под каждый дистрибутив. - Контейнеры и Kubernetes. systemd стал главным потребителем и двигателем cgroups v2 (единая иерархия).
Когда их включила Fedora 31, Docker, runc и Kubernetes были вынуждены их поддержать. Сегодня Kubernetes
рекомендует драйвер cgroup
systemd, чтобы kubelet и systemd не делили одни cgroups двумя менеджерами. - Стандартизация мелочей, которые раньше у всех были свои:
/etc/os-release,/etc/machine-id, предсказуемые имена интерфейсов,tmpfiles.d,sysusers.d, продвижение usrmerge (/bin→/usr/bin). Позже это оформилось в спецификации UAPI Group. - Супервизия как норма. Перезапуск упавшего сервиса, лимиты памяти и CPU, песочница (
ProtectSystem=,PrivateTmp=, фильтры системных вызовов) - несколько строк unit-файла, а не отдельный софт. - Структурированные логи. journald хранит записи с полями (
_PID,_SYSTEMD_UNIT,PRIORITY), а не строки.journalctl -u nginx --since "1 hour ago" -p errстал стандартом диагностики. - Доверенная загрузка и immutable-системы. systemd-boot, UKI (unified kernel image: ядро + initrd +
командная строка в одном подписанном EFI-файле), measured boot с TPM2,
systemd-sysextдля неизменяемых образов. На этом строятся Fedora Silverblue, CoreOS, SteamOS - и ровно в эту сторону пошёл Поттеринг с Amutable. - Рабочий стол. logind - стандарт сессий, мест (seats), прав на устройства и блокировок сна. GNOME, KDE и Wayland-композиторы опираются на него.
Как systemd устроен¶
Загрузка¶
UEFI/BIOS
└─► загрузчик (GRUB или systemd-boot)
└─► ядро + initramfs
└─► systemd внутри initramfs (PID 1)
├─ находит и монтирует корень (cryptsetup, LVM, RAID)
└─► switch-root в настоящий корень
└─► systemd (тот же PID 1, перезапущенный из корня)
├─ генераторы: /etc/fstab → .mount-юниты и т.д.
├─ граф зависимостей от default.target
├─ сокеты, файловые системы, сервисы - параллельно
└─► multi-user.target / graphical.target: система готова
systemd-analyze blame # кто сколько грузился
systemd-analyze critical-chain # цепочка, которая определила общее время загрузки
Юниты¶
Юнит - объект, которым управляет systemd. Тип - по расширению файла.
| Тип | Что описывает |
|---|---|
.service |
Процесс или демон |
.socket |
Сокет для socket activation: пришло соединение - запустить сервис |
.target |
Точка синхронизации, группа юнитов. Замена runlevels: multi-user.target ≈ runlevel 3 |
.mount, .automount |
Точка монтирования, automount - при первом обращении |
.swap |
Раздел или файл подкачки |
.device |
Устройство, появившееся через udev |
.timer |
Таймер, замена cron |
.path |
Наблюдение за путём: изменился файл - запустить юнит |
.slice |
Узел дерева cgroups для лимитов ресурсов: system.slice, user.slice |
.scope |
Группа процессов, запущенных не systemd, но взятых под учёт: например, сессия пользователя |
- где лежат:
/usr/lib/systemd/system/- от пакетов,/etc/systemd/system/- от администратора и приоритетнее,/run/systemd/system/- временные - drop-in:
foo.service.d/override.conf(systemctl edit foo) поверх оригинала, не трогая его - шаблоны:
getty@.serviceразворачивается вgetty@tty1.service, внутри%i = tty1
Зависимости, порядок, транзакции¶
systemd разделяет две независимые оси:
- требования -
Wants=,Requires=,BindsTo=: что ещё поднять - порядок -
After=,Before=: в какой последовательности
Запуск юнита - это транзакция:
- systemd собирает все нужные юниты по зависимостям.
- Проверяет граф на циклы и конфликты (
Conflicts=), выбрасывает лишнее. - Превращает результат в jobs (start, stop, restart) в очереди. Jobs без отношений порядка выполняются параллельно.
Нашёлся цикл - systemd удаляет из транзакции один из необязательных юнитов и пишет об этом в журнал.
cgroups¶
Каждый сервис живёт в своей cgroup: /sys/fs/cgroup/system.slice/nginx.service/. Процесс не может выйти из неё
сам, потомки наследуют группу.
systemctl stopубивает всё в группе (KillMode=control-group)systemctl statusпоказывает настоящее дерево процессов сервиса- лимиты
MemoryMax=,CPUQuota=,TasksMax=- просто атрибуты cgroup
systemd-cgls # дерево cgroups с процессами
systemd-cgtop # потребление ресурсов по cgroups в реальном времени
Socket activation¶
- systemd читает
foo.socket, создаёт сокет и слушает его сам. - Приходит первое соединение - или сразу при загрузке, ради параллельности.
- systemd запускает
foo.serviceи передаёт ему уже открытые файловые дескрипторы начиная с номера 3. ПеременныеLISTEN_FDS=1иLISTEN_PID=<pid>говорят, сколько их. - Сервис через
sd_listen_fds()забирает сокет и работает с ним как с обычным.
Бонус: сервис можно перезапустить, не потеряв ни одного соединения. Сокет всё это время держит systemd, а входящие ждут в очереди ядра.
Готовность сервиса: sd_notify¶
При Type=notify systemd выставляет переменную NOTIFY_SOCKET. Сервис шлёт туда датаграмму READY=1, так же
передаются STATUS=..., WATCHDOG=1 («я жив» для watchdog), RELOADING=1. Протокол тривиальный, и вся
libsystemd для него не нужна - что и выяснилось на истории с xz.
Как с systemd разговаривают¶
- D-Bus - основной API менеджера:
systemctlвызывает методы объектаorg.freedesktop.systemd1. Пока шина не поднялась (ранняя загрузка) - приватный сокет/run/systemd/private - Varlink - более новый и простой IPC: JSON поверх Unix-сокетов. Компоненты всё активнее переходят на него (userdb, homed, resolved): D-Bus тяжёлый и сам зависит от уже работающей системы
Генераторы¶
Генератор - маленькая программа, которую systemd запускает очень рано, до построения графа. Она превращает
чужие конфиги в юниты: systemd-fstab-generator делает из каждой строки /etc/fstab .mount-юнит. Так
systemd держал совместимость: SysV-скрипты много лет превращал в юниты systemd-sysv-generator, пока v260 его не
удалила.
Состав проекта¶
| Компонент | Что делает | Что заменил |
|---|---|---|
systemd (PID 1) |
Менеджер системы и сервисов | sysvinit, Upstart |
systemd --user |
Такой же менеджер для сервисов пользователя | - |
journald |
Журнал: структурированные записи с метаданными, бинарные файлы, ротация, опционально пересылка в syslog | Частично rsyslog и syslog-ng |
udevd |
Устройства: правила, имена, права, события hotplug | Влит в проект в 2012 |
logind |
Сессии пользователей, seats, права на устройства, блокировки сна и выключения | ConsoleKit |
networkd |
Настройка сети на серверах и в контейнерах | ifupdown, network-scripts. На десктопе обычно NetworkManager |
resolved |
Кэширующий DNS-резолвер: DNSSEC, DNS-over-TLS, сплит-DNS для VPN | dnsmasq, nscd |
timesyncd |
Простой SNTP-клиент | ntpd. Для серверов точнее chrony |
homed |
Переносимые, при желании зашифрованные домашние каталоги с метаданными пользователя | Классические /home + /etc/passwd |
oomd |
OOM-killer в userspace на метриках давления памяти (PSI) | Поздний OOM-killer ядра |
machined, nspawn |
Регистрация ВМ и контейнеров, лёгкие контейнеры | chroot «на стероидах» |
tmpfiles, sysusers |
Временные файлы и каталоги, системные пользователи из декларативных файлов | Логика в postinstall-скриптах пакетов |
systemd-boot, ukify |
Простой UEFI-загрузчик, сборка UKI | GRUB на UEFI-системах |
cryptsetup, repart, sysext |
Шифрование дисков, разметка при загрузке, расширения неизменяемого образа | Самописные скрипты в initramfs |
run0 |
Запуск команды от другого пользователя без SUID-бинарника | sudo |
coredump |
Сбор и хранение дампов упавших процессов | core в текущем каталоге |
hostnamectl, timedatectl, localectl, loginctl, networkctl, resolvectl |
Единые утилиты администрирования | Разные конфиги в разных дистрибутивах |
Note
Это один репозиторий и одна команда, но не монолитный бинарник, а десятки отдельных программ. Многие компоненты опциональны и выключаются при сборке: можно жить с systemd в роли init без networkd, resolved и homed. Так и делают многие дистрибутивы.
Альтернативы¶
| Система | Модель | Где живёт |
|---|---|---|
| sysvinit | Классика: скрипты и runlevels | Devuan (по выбору), Slackware, MX Linux |
| OpenRC | Скрипты с зависимостями поверх любого init, опциональная супервизия | Gentoo, Alpine, Artix |
| runit | Минималистичная супервизия в духе daemontools | Void Linux, Artix |
| s6 / s6-rc | Супервизия + менеджер зависимостей, очень строгий дизайн (Laurent Bercot) | Artix, Obarun, контейнеры (s6-overlay) |
| dinit | Современный компактный менеджер сервисов с зависимостями на C++ | Chimera Linux, Artix |
| GNU Shepherd | Сервисы описываются на Scheme (Guile) | GNU Guix |
| launchd | Источник идеи socket activation | macOS |
| SMF | Сервисы с манифестами и зависимостями | Solaris, illumos |
| rc.d | Скрипты BSD | FreeBSD, OpenBSD, NetBSD |
| Upstart | Событийная модель | Почти вымер |
Прослойки, чтобы жить без systemd:
- eudev - udev без systemd
- elogind - logind без systemd, чтобы работали GNOME и KDE
- ConsoleKit2 - форк ConsoleKit
См. Дистрибутивы Linux.
За и против¶
За:
- быстрая параллельная загрузка
- надёжная супервизия
- cgroups и песочница из коробки
- один интерфейс на все дистрибутивы
- структурированные логи
- активная разработка и поддержка крупнейших вендоров
Против:
- нарушение «философии UNIX» (одна программа - одна задача): проект поглотил десятки областей
- связанность: части десктопа и софта начинают требовать компоненты systemd, и выбор init перестаёт быть свободным
- бинарный журнал: без
journalctlне прочитатьgrep-ом, повреждённый файл спасать сложнее - большая поверхность атаки: PID 1 и окружение - сотни тысяч строк на C. xz показал цену связанности
- стиль команды: «работает как задумано» в ответ на баг-репорты, конфликты с ядром, Debian и пользователями
Взвешенно. Технически systemd решил реальные проблемы, которые SysV не решал 20 лет. Поэтому его и приняли
технические комитеты почти всех мейнстримных дистрибутивов. Претензии к масштабу и связанности тоже обоснованы.
Поэтому живут альтернативы, а сам systemd постепенно делает части опциональными: dlopen вместо жёстких
зависимостей, поддержка musl.
Итого:
- systemd - PID 1 + целый слой системной обвязки Linux: сервисы, журнал, устройства, сессии, сеть, загрузка
- создан в 2010 году Поттерингом и Зиверсом в Red Hat. Red Hat поддержал, потому что проект решал задачи энтерпрайза: быстрая загрузка, супервизия, единое администрирование, cgroups под контейнеры
- ключевые идеи: socket activation, трекинг через cgroups, декларативные юниты, зависимости вместо событий, транзакции
- перелом - 2014 год: Debian, RHEL 7, SLES 12, капитуляция Upstart. К 2015 году мейнстрим на systemd
- влияние: единое администрирование, cgroups v2 и драйвер cgroup в Kubernetes, стандартизация
(
os-release,machine-id, имена интерфейсов), доверенная загрузка и immutable-ОС - 2025-2026: удалены cgroups v1 и поддержка SysV-скриптов (v260), экспериментальная поддержка musl, создатель ушёл строить «верифицируемый Linux» в Amutable
Источники¶
- Systemd - Wikipedia
- LWN: Rethinking PID 1 (2010), LWN: обсуждение и ответ Upstart
- LWN: решение технического комитета Debian (февраль 2014), LWN Weekly, 13 февраля 2014
- iTWire: итоги общего голосования Debian, OSNews: результаты GR
- Upstart - Wikipedia, Ubuntu 15.04 release notes, Linux Magazine: Ubuntu Switches to systemd
- Kay Sievers - Wikipedia, Computerworld: Linus Torvalds suspends key Linux developer, LKML: cmdline: Hide "debug"
- GNOME and logind+systemd thoughts, Arch: ConsoleKit replaced by logind, GNOME ConsoleKit project page
- LWN: kdbus и bus1, Phoronix: BUS1 и dbus-broker
- LWN: xz backdoor, oss-security: xz и libsystemd, oss-security: dlopen-изменения systemd
- Linuxiac: systemd 258 drops cgroup v1, Linuxiac: systemd 259, Phoronix: systemd 260 released
- Phoronix: systemd lands experimental musl support, The Register: systemd 259 rc и musl
- The Register: Poettering quits Microsoft (январь 2026), Linuxiac: Poettering goes to Microsoft (2022)