Что такое init system
Когда Linux загружается, после kernel initialization запускается первый процесс — PID 1. Этот процесс отвечает за: монтирование оставшихся ФС, запуск всех остальных сервисов в правильном порядке, обработку сигналов (что делать когда ctrl+alt+del, что делать при shutdown), reap-инг zombie-процессов, перезапуск упавших сервисов.
PID 1 называется init system. Без него Linux загрузится до командной строки и зависнет — ему некому делегировать дальнейшую работу.
На современных дистрибутивах (Ubuntu 26.04 LTS, Debian 13 Trixie, RHEL 9/10, Fedora) init system — это systemd. Версия 257+ как раз в наших целевых OS. До 2014-2016 годов был SysV init или Upstart. Переход на systemd был долгим и спорным, но к 2026 году systemd — фактический стандарт.
Почему systemd, а не старый SysV init
SysV init — это набор /etc/init.d/* shell-скриптов, запускаемых последовательно при boot. Каждый скрипт выглядел примерно так:
#!/bin/sh
# /etc/init.d/apache
case "$1" in
start) ... ;;
stop) ... ;;
restart) ... ;;
esac
Проблемы такого подхода:
Каждая проблема SysV — это feature systemd.
systemd взял на себя то, что раньше делали разные инструменты: init + cron + inetd + supervisord + syslog + udev + automount. Это и его плюс (всё в одном, согласованный API), и минус (огромный monolithic компонент, критикуемый за «нарушение Unix-философии»).
Для Junior DE: systemd — это данность. На любой современной production-VM ты будешь работать с systemd. SysV скрипты иногда встретятся как legacy /etc/init.d/* — systemd их умеет запускать через compatibility layer.
PID 1: что значит
$ ps -p 1
PID TTY TIME CMD
1 ? 00:00:42 systemd
$ readlink /proc/1/exe
/usr/lib/systemd/systemd
PID 1 — это /usr/lib/systemd/systemd. Если он упадёт — kernel panic, перезагрузка. Поэтому код systemd очень аккуратный, на C, с десятилетиями полировки.
PID 1 особенный: ему ядро не доставляет сигналы, которые не обработаны. Это значит — kill 1 без обработчика не убьёт init. Зато systemctl reboot / systemctl poweroff — это API через D-Bus, который systemd слушает.
Юниты: всё это units
systemd оперирует абстракцией unit — описание того, чем нужно управлять. Юниты бывают разных типов:
Каждый тип отвечает за свой класс сущностей. Расширение файла указывает тип.
Для DE на повседневной работе важны: .service, .timer, .target. Остальные — изредка, в специфических случаях.
Где живут unit-файлы
Поиск идёт в нескольких директориях по приоритету:
/etc/systemd/system/ # высший приоритет — admin override
/run/systemd/system/ # runtime (создаётся при работе)
/usr/lib/systemd/system/ # пакетные unit-файлы (postgres, nginx)
Когда устанавливаешь пакет (apt install postgresql), его unit-файл попадает в /usr/lib/systemd/system/postgresql.service. Если хочешь его изменить — не редактируй там, потому что apt upgrade перезапишет. Правильный способ — override:
$ sudo systemctl edit postgresql
Эта команда создаст /etc/systemd/system/postgresql.service.d/override.conf, который дополнит базовый unit. Тут можно переопределить ExecStart, добавить Environment=, изменить Restart=.
# Просмотр всех unit-директорий с приоритетом:
$ systemctl --no-pager show -p UnitPath
UnitPath=/etc/systemd/system.control /run/systemd/system.control /run/systemd/transient /etc/systemd/system /run/systemd/system /usr/lib/systemd/system ...
User-level units
systemd умеет запускать unit-ы от имени пользователя, без root. Они живут в ~/.config/systemd/user/:
# Запустить как user (не системный)
$ systemctl --user start my-etl.service
Это полезно для DE: тестовый ETL-скрипт можно запустить как user, без sudo. Подробнее в уроке 04-writing-service-unit.
Targets вместо runlevels
В SysV было 7 runlevels (0-6): single-user, multi-user, graphical, reboot, halt. systemd использует targets — гибче, потому что target может зависеть от любого набора units.
$ systemctl get-default
multi-user.target
$ systemctl list-units --type=target --state=active
UNIT LOAD ACTIVE SUB DESCRIPTION
basic.target loaded active active Basic System
graphical.target loaded active active Graphical Interface
multi-user.target loaded active active Multi-User System
network-online.target loaded active active Network is Online
network.target loaded active active Network
remote-fs.target loaded active active Remote File Systems
sysinit.target loaded active active System Initialization
timers.target loaded active active Timers
...
Стандартные targets:
default.target— что boot-ит по умолчанию. Обычно symlink наmulti-user.target(для server) илиgraphical.target(для desktop).multi-user.target— все системные сервисы, network up, но без GUI.graphical.target— multi-user + display manager.rescue.target— single-user, minimal system для recovery.emergency.target— даже меньше, только root shell без mounts.network-online.target— сеть готова и есть DNS.
DE-юниты обычно указывают WantedBy=multi-user.target в [Install] — это значит «при boot до multi-user меня тоже запусти».
Что systemd делает под капотом
Когда ты делаешь systemctl start nginx.service, происходит много всего:
systemd не просто 'запускает binary' — он выстраивает целое окружение для процесса.
Эта последовательность объясняет, почему systemctl status показывает столько метаданных и почему systemd-юниты по умолчанию надёжнее, чем nohup python my_script.py & в shell.
Куда дальше
В следующих уроках:
02-systemctl-basics— основные команды для управления сервисами.03-journalctl-logs—journalctlдля чтения логов.04-writing-service-unit— создаём свой.serviceдля custom DE-задачи.
Cron — в модуле 15-cron-scheduling. Bash-скрипты для запуска через systemd — в модуле 16-bash-scripting-basics.
Проверь установку systemd
# Запустился ли systemd как PID 1
$ ps -p 1 -o comm=
systemd
# Версия systemd
$ systemctl --version
systemd 257 (257.1-1ubuntu1)
+PAM +AUDIT +SELINUX +APPARMOR +IMA +SMACK +SECCOMP ...
# Текущий default target
$ systemctl get-default
multi-user.target
# Какие unit-файлы есть для одного из сервисов
$ systemctl list-unit-files | grep ssh
ssh.service enabled enabled
sshd.service enabled enabled
Попробуй сам
- Что у тебя PID 1?
ps -p 1 -o comm= - Какая версия systemd?
systemctl --version | head -1 - Сколько units сейчас активных?
systemctl list-units --state=active | wc -l - Какие targets активны?
systemctl list-units --type=target --state=active - Default target:
systemctl get-default - Посмотри один из системных unit-файлов:
systemctl cat ssh.service
macOS-различия
- На macOS init system — launchd, не systemd. Файлы
.plistв/Library/LaunchDaemons/или~/Library/LaunchAgents/. Управление:launchctl load/unload/start/stop. - Командой
brew servicesHomebrew абстрагирует это для брю-пакетов (brew services start postgresql). - Для DE на macOS обычно Docker Desktop или OrbStack, и внутри VM уже systemd. Так что systemd-команды релевантны при
sshна production Linux.
Главное
- systemd — init system, PID 1, на современных Ubuntu/Debian/RHEL/Fedora.
- Заменил SysV init: parallel boot, deps между units, встроенный supervisor (
Restart=), journal, cgroups. - Управляет всем: services, timers, mounts, sockets, paths, targets.
- Unit — описание управляемой сущности. Типы:
.service,.timer,.target,.mount,.socket,.path, … - Unit-файлы:
/usr/lib/systemd/system/(пакеты),/etc/systemd/system/(admin override). - User-units:
~/.config/systemd/user/— без root. - Target — группа units, заменили runlevels.
multi-user.target— стандарт для server. - При
systemctl start: deps -> cgroup -> limits -> namespaces -> fork+exec -> route I/O в journal -> monitor. - Для DE: понимать systemd обязательно — каждый production-VM на нём.