Когда машина грузится, кто-то должен решить: какие службы поднять, в каком порядке, что считать признаком готовности системы. На современных Linux этим занимается systemd - первый процесс (PID 1), родитель всего остального. В этом уроке разбираем, как управлять службами через systemctl, что такое юниты и цели (targets), чем они отличаются от старых runlevel, как переключать режимы работы на лету и как корректно гасить и перезагружать систему, не оборвав работу пользователям.

Как это работает
systemd описывает все управляемые сущности через юниты (units) - текстовые файлы с расширением, задающим тип. Самые частые: .service (демон или разовая задача), .target (группа-точка синхронизации), .socket (сокет для активации по требованию), .mount и .automount (точки монтирования), .timer (замена cron внутри systemd), .device, .path, .slice. Тип определяет, какие секции в файле осмысленны и как systemd обращается с объектом.
Юниты лежат в трёх слоях, и порядок важен. Пакеты кладут эталонные файлы в /usr/lib/systemd/system. Администратор переопределяет их в /etc/systemd/system - этот слой главнее. Времянка, генерируемая на лету, живёт в /run/systemd/system. Если имя совпадает, выигрывает более приоритетный путь, а через drop-in каталоги вида имя.service.d/override.conf можно менять отдельные параметры, не трогая исходный файл.
Главная идея systemd - не последовательность шагов, а граф зависимостей. Вместо номерных уровней есть цели: точки, в которых собирается нужный набор служб. Связи Wants= и Requires= тянут юниты внутрь цели, а Before= и After= задают порядок запуска. Благодаря этому графу systemd стартует независимые службы параллельно, отчего загрузка ощутимо быстрее старого последовательного SysVinit.
Старые runlevel (0-6) никуда не делись как понятие, но теперь это просто синонимы целей. Для совместимости заведены символические ссылки: runlevel3.target указывает на multi-user.target (текстовый многопользовательский режим), runlevel5.target - на graphical.target (с графической оболочкой), runlevel1.target - на rescue.target. Команды telinit и runlevel ещё работают, но это фасад над systemctl. То, какая цель грузится по умолчанию, задаёт ссылка default.target.
Команды и примеры
Базовое управление службой одинаково в Debian/Ubuntu и RHEL/Fedora - сам systemctl от дистрибутива не зависит, различаются лишь имена пакетов и юнитов (например, ssh.service в Debian/Ubuntu против sshd.service в RHEL/Fedora):
Код: Выделить всё
systemctl status sshd.service # состояние, последние строки лога, PID
systemctl start sshd # запустить сейчас
systemctl stop sshd # остановить сейчас
systemctl restart sshd # перезапуск
systemctl reload sshd # перечитать конфиг без полного рестарта
systemctl enable --now sshd # включить автостарт И сразу запустить
systemctl disable sshd # убрать из автозагрузки
systemctl is-enabled sshd # enabled / disabled / static / masked
systemctl is-active sshd # active / inactive / failed
Осмотр системы и работа с целями:
Код: Выделить всё
systemctl list-units --type=service # активные службы
systemctl list-units --type=service --all # включая неактивные
systemctl --failed # что упало
systemctl get-default # текущая цель по умолчанию
systemctl set-default multi-user.target # грузиться в текст без GUI
systemctl list-dependencies graphical.target # дерево зависимостей цели
Код: Выделить всё
systemctl isolate multi-user.target # уйти из графики в текст без перезагрузки
systemctl isolate graphical.target # вернуть графику
systemctl rescue # = isolate rescue.target, однопользовательский
systemctl emergency # минимум: только / в ro, без большинства служб
Корректное завершение работы. Команды-обёртки и их systemctl-эквиваленты:
Код: Выделить всё
systemctl poweroff # = shutdown -h now, выключить питание
systemctl reboot # = shutdown -r now, перезагрузка
systemctl halt # остановить ЦП без выключения питания
shutdown -h +10 "Перезагрузка через 10 минут, сохраните работу"
shutdown -r 22:30 # перезагрузка в 22:30
shutdown -c # отменить запланированное завершение
Код: Выделить всё
wall "Через 5 минут плановый ребут, закройте сессии"
- Путают enable и start: включили enable, удивляются, что служба не работает прямо сейчас - до перезагрузки её надо ещё и start (или сразу enable --now).
- isolate на сетевой машине: если выполнить isolate rescue.target по SSH, сеть и sshd погаснут, и вы потеряете доступ. Делайте такое только с консоли.
- Маскированная служба (systemctl mask) не запустится ни вручную, ни как зависимость - ссылка ведёт на /dev/null. Пока не сделаете unmask, start будет тихо игнорироваться.
- Отредактировали юнит в /etc/systemd/system и забыли systemctl daemon-reload - systemd работает по старой версии в памяти и ваших правок не видит.
- Имя ssh против sshd: команда из RHEL-инструкции не сработает в Debian и наоборот. Сверяйтесь с list-units.
- reload не у всех юнитов есть; если служба не умеет перечитывать конфиг, нужен restart (или try-restart).
- halt без -p лишь останавливает систему, не снимая питание - на железе машина продолжит гудеть. Для выключения нужен poweroff или halt -p.
- Посмотрите текущую цель по умолчанию: systemctl get-default.
- Поставьте текстовый режим: systemctl set-default multi-user.target, затем проверьте get-default.
- Переключитесь в текст без перезагрузки: systemctl isolate multi-user.target (с локальной консоли, не по SSH), убедитесь, что графика погасла.
- Запустите учебную службу: systemctl enable --now sshd, проверьте is-enabled и is-active.
- Замаскируйте её: systemctl mask sshd, попробуйте start и посмотрите, что вывел systemctl status; затем unmask.
- Изучите дерево цели: systemctl list-dependencies graphical.target.
- Запланируйте и отмените ребут: shutdown -r +5 "тест", затем shutdown -c; верните default.target обратно в graphical.target.
- В чём практическая разница между systemctl enable foo и systemctl start foo?
- Какой цели соответствуют классические runlevel 3 и 5 и где об этом узнать в системе?
- Что делает systemctl isolate и чем он опасен на удалённом сервере?
- Чем emergency.target отличается от rescue.target по набору смонтированных ФС и запущенных служб?
- Какие три каталога хранят unit-файлы и какой из них имеет приоритет при совпадении имён?
- Почему после правки unit-файла нужен systemctl daemon-reload и что произойдёт без него?