Основы

systemd: что это, как работает и как управлять сервисами в Linux

Обновлено: · Skillaria.Top

systemd — система инициализации и менеджер служб Linux: он запускается ядром первым процессом (PID 1), поднимает остальные службы в нужном порядке и следит за ними. Всем, что делает systemd, управляют через юниты — текстовые описания сервисов, таймеров, точек монтирования; командой systemctl их запускают, останавливают и добавляют в автозагрузку, а journalctl показывает их логи.

systemd — это система инициализации и менеджер служб, который используется в большинстве современных дистрибутивов Linux: Debian, Ubuntu, Fedora, RHEL и их производных. Ядро после загрузки запускает systemd первым процессом с PID 1, а дальше уже он поднимает сеть, монтирует диски, запускает веб-сервер, базу данных и всё остальное. Если коротко отвечать на вопрос «systemd что это», то это «диспетчер», который знает, какие службы должны работать, в каком порядке их стартовать и что делать, если служба упала.

Проверить, что у вас именно systemd, просто:

$ ps -p 1 -o comm=
systemd

Зачем понадобился systemd

Раньше в Linux использовалась SysV init: набор shell-скриптов в /etc/init.d/, которые запускались по очереди. Схема была понятной, но медленной и хрупкой. Каждый скрипт сам писал PID-файл, сам решал, как проверить, жив ли процесс, а перезапуск упавшей службы приходилось прикручивать отдельно.

systemd решает эти задачи централизованно:

  • Параллельный запуск. Службы стартуют одновременно, если между ними нет зависимостей, поэтому загрузка быстрее.
  • Зависимости и порядок. В описании службы явно указано, что ей нужно (например, сеть) и после чего её запускать.
  • Надзор. systemd знает все процессы службы через cgroups и может перезапустить её при сбое.
  • Единый журнал. Вывод всех служб собирает journald, логи смотрят одной командой.
  • Единый интерфейс. Любая служба управляется одинаково: systemctl start|stop|restart|status.

Кроме менеджера служб, в проект systemd входит набор компонентов: journald (журнал), logind (сессии пользователей), timesyncd (синхронизация времени), resolved (DNS), networkd (сеть). Не все дистрибутивы используют их все, но systemd как PID 1 и journald есть почти везде.

Юниты: из чего состоит systemd

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

ТипРасширениеЧто описывает
service.serviceСлужбу — процесс-демон или разовую задачу
timer.timerЗапуск другого юнита по расписанию (замена cron)
socket.socketСокет, при обращении к которому запускается служба
target.targetГруппу юнитов, «состояние системы» (например, multi-user.target)
mount.mountТочку монтирования
path.pathСлежение за файлом или каталогом

Где лежат unit-файлы

Файлы юнитов хранятся в нескольких каталогах, и у них есть приоритет:

  • /usr/lib/systemd/system/ (в Debian и Ubuntu также /lib/systemd/system/) — юниты, установленные пакетами. Руками их не правят: обновление пакета перезапишет изменения.
  • /etc/systemd/system/ — юниты и переопределения администратора. У них наивысший приоритет.
  • /run/systemd/system/ — временные юниты, созданные во время работы.

Чтобы посмотреть итоговое содержимое юнита со всеми переопределениями, используйте systemctl cat nginx.service.

Targets вместо уровней запуска

Старые runlevel заменены целями (targets). multi-user.target — обычный серверный режим без графики, graphical.target — с графической оболочкой, rescue.target — однопользовательский режим восстановления. Текущая цель по умолчанию показывается командой systemctl get-default, меняется через systemctl set-default multi-user.target.

systemctl: управление службами

systemctl — основной инструмент для работы с systemd. Большинство команд меняют состояние системы и требуют sudo.

КомандаЧто делает
systemctl status nginxСостояние службы, PID, память, последние строки лога
systemctl start nginxЗапустить сейчас
systemctl stop nginxОстановить
systemctl restart nginxПерезапустить (stop + start)
systemctl reload nginxПеречитать конфигурацию без остановки (если служба умеет)
systemctl enable nginxДобавить в автозапуск
systemctl disable nginxУбрать из автозапуска
systemctl enable --now nginxВключить автозапуск и сразу запустить
systemctl is-active nginxВывести active/inactive — удобно в скриптах
systemctl list-units --type=serviceЗагруженные службы
systemctl --failedУпавшие юниты
systemctl daemon-reloadПеречитать unit-файлы после правки

Как читать systemctl status

$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running) since Mon 2026-10-12 09:14:03 UTC; 2h 5min ago
       Docs: man:nginx(8)
   Main PID: 812 (nginx)
      Tasks: 3 (limit: 2307)
     Memory: 6.1M
        CPU: 154ms
     CGroup: /system.slice/nginx.service
             ├─812 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
             ├─813 "nginx: worker process"
             └─814 "nginx: worker process"

Строка Loaded говорит, откуда взят unit-файл и включён ли автозапуск (enabled). Строка Active — текущее состояние: active (running), inactive (dead) или failed. В блоке CGroup видны все процессы службы — именно так systemd отслеживает, что ей принадлежит.

Чем enable отличается от start

Это частая путаница. start запускает службу прямо сейчас, но после перезагрузки она не поднимется. enable создаёт символическую ссылку в каталоге цели (например, /etc/systemd/system/multi-user.target.wants/), и служба стартует при загрузке, но сейчас она не запускается. Нужно и то и другое — используйте enable --now.

Есть и третье состояние — mask. systemctl mask service связывает юнит с /dev/null, и его нельзя запустить ни вручную, ни как зависимость. Пригодится, когда службу нужно гарантированно выключить.

journalctl: логи служб

Всё, что служба пишет в stdout и stderr, перехватывает systemd-journald и сохраняет в бинарный журнал вместе с метаданными: имя юнита, PID, приоритет, время. Читают журнал командой journalctl.

journalctl -u nginx              # логи одной службы
journalctl -u nginx -f           # следить в реальном времени, как tail -f
journalctl -u nginx --since "1 hour ago"
journalctl -u nginx -n 50        # последние 50 строк
journalctl -b                    # с момента текущей загрузки
journalctl -b -1                 # предыдущая загрузка
journalctl -p err -b             # только ошибки и серьёзнее
journalctl -k                    # сообщения ядра
journalctl --disk-usage          # сколько места занимает журнал

Флаг -p фильтрует по приоритету syslog: emerg, alert, crit, err, warning, notice, info, debug. Указанный уровень включает всё, что серьёзнее него.

Журнал после перезагрузки

Если каталог /var/log/journal не существует, а в /etc/systemd/journald.conf стоит Storage=auto, журнал хранится только в памяти (/run/log/journal) и пропадает при перезагрузке. Чтобы сделать его постоянным, задайте Storage=persistent или создайте каталог и перезапустите journald. Размер ограничивает параметр SystemMaxUse=, а почистить старое можно командой journalctl --vacuum-time=2weeks или --vacuum-size=500M.

journald часто работает в паре с rsyslog: журнал передаёт сообщения в rsyslog, а тот пишет классические текстовые файлы в /var/log/ и умеет отправлять логи на центральный сервер.

Автозапуск своего сервиса: пример unit-файла

Допустим, у вас есть приложение — скрипт или бинарник, которое нужно держать запущенным, поднимать при загрузке и перезапускать при падении. Создайте файл /etc/systemd/system/myapp.service:

[Unit]
Description=My web application
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
EnvironmentFile=/etc/myapp/env
ExecStart=/opt/myapp/bin/server --port 8080
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Разберём секции:

  • [Unit] — описание и зависимости. After= задаёт только порядок, Wants= — мягкую зависимость (подтянуть юнит, но не падать, если он не поднялся). Жёсткая зависимость — Requires=.
  • [Service] — как запускать. Type=simple означает, что процесс из ExecStart и есть служба и он не уходит в фон. User= запускает от непривилегированного пользователя. Restart=on-failure перезапускает службу, если она завершилась с ошибкой, через RestartSec секунд.
  • [Install] — что делает enable. WantedBy=multi-user.target означает «запускать при обычной загрузке».

Применяем:

sudo useradd --system --no-create-home --shell /usr/sbin/nologin myapp
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
systemctl status myapp
journalctl -u myapp -f

Частые ошибки в unit-файлах

  • Относительный путь в ExecStart. Путь к программе должен быть абсолютным. systemd не ищет команды в PATH пользователя так, как это делает оболочка.
  • Забыли daemon-reload. После правки файла systemd продолжает использовать старую версию и предупреждает об этом в status.
  • Демон уходит в фон. Если программа сама форкается, а указан Type=simple, systemd решит, что служба завершилась. Либо запускайте программу в режиме foreground, либо используйте Type=forking с PIDFile=.
  • Переменные окружения из профиля. Служба не видит ~/.bashrc и /etc/profile. Переменные задаются через Environment= или EnvironmentFile=.

Переопределение без правки пакетного юнита

Чтобы изменить параметры службы из пакета, не трогая её файл, используйте drop-in:

sudo systemctl edit nginx

Откроется редактор, и изменения сохранятся в /etc/systemd/system/nginx.service.d/override.conf. Например, туда можно дописать [Service] и Restart=always. После выхода из редактора systemd сам перечитает конфигурацию.

Таймеры systemd вместо cron

Таймер — это юнит, который запускает одноимённый сервис по расписанию. Плюсы перед cron: логи задачи в журнале, зависимости, пропущенные запуски можно догнать (Persistent=true). Пример — ежедневный бэкап:

# /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh

# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily

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

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers

Проверить выражение OnCalendar можно командой systemd-analyze calendar "*-*-* 03:00:00" — она покажет, когда случится следующий запуск.

Диагностика загрузки

systemd хранит время старта каждого юнита, поэтому медленную загрузку легко разобрать:

systemd-analyze                  # общее время загрузки
systemd-analyze blame            # юниты, отсортированные по времени запуска
systemd-analyze critical-chain   # цепочка, которая задержала загрузку
systemd-analyze verify /etc/systemd/system/myapp.service   # проверка unit-файла

Итог

systemd — это PID 1 и менеджер служб в современном Linux. Он описывает всё юнитами, управляется через systemctl, собирает логи в журнал, который читается journalctl, а вместо cron может запускать задачи таймерами. Чтобы уверенно им пользоваться, достаточно освоить status, enable --now, journalctl -u и уметь написать простой unit-файл с Restart=on-failure. На практике systemd, journald и логирование разобраны в курсе по Linux.

Частые вопросы

Как узнать, используется ли systemd в моей системе?

Выполните ps -p 1 -o comm= — если вывод systemd, система работает под systemd. Также есть каталог /run/systemd/system, который существует только при загрузке через systemd.

В чём разница между systemctl restart и reload?

restart полностью останавливает и снова запускает службу, соединения при этом обрываются. reload просит службу перечитать конфигурацию без остановки, но работает только если в юните задан ExecReload.

Можно ли запускать сервисы systemd от обычного пользователя без sudo?

Да, у systemd есть пользовательский экземпляр: юниты кладут в ~/.config/systemd/user/ и управляют ими через systemctl --user. Чтобы они работали без активной сессии, нужно включить loginctl enable-linger для пользователя.

Почему служба в статусе failed и как сбросить это состояние?

Причину ищите в journalctl -u имя -b и в строке Active команды status. После исправления запустите службу снова, а метку failed без перезапуска сбрасывает systemctl reset-failed.

Где хранятся логи systemd на диске?

При постоянном хранении — в /var/log/journal/ в бинарном формате, иначе в /run/log/journal/ в памяти. Читать их нужно через journalctl, а не текстовыми утилитами.

Разберите тему на видео

Эта тема подробно разобрана с практикой в курсе «Linux: с нуля до уверенного администрирования».

Перейти к курсу