Введение: Почему SysVinit умер, и при чём тут Systemd
Представьте себе повара, который готовит ужин на 10 человек, но строго по одному блюду за раз — сначала суп, потом только начинает нарезать салат. Именно так работала старая система инициализации SysVinit: запускала службы строго по одной, в заранее заданном порядке. Независимо от того, зависят ли они друг от друга.
С усложнением Linux-систем это стало болью:
Медленная загрузка. Служба A ждёт завершения службы B, даже если между ними нет никакой реальной зависимости.
Нет контроля за процессами. Запустил — и забыл. Упал дочерний процесс? SysVinit об этом не знает.
Хаос в логах. Каждый сервис пишет куда хочет: один в
/var/log/nginx/, другой в syslog, третий в/tmp/. Никакой единой точки входа.Хрупкие скрипты. Shell-скрипты в
/etc/init.d/— это огромное поле для ошибок и несовместимостей между дистрибутивами.
В 2010 году Леннарт Поттеринг (Lennart Poettering) представил systemd — систему, которая решала все эти проблемы разом. Параллельный запуск, граф зависимостей, контрольные группы, централизованные логи. Сообщество поначалу встретило его в штыки (споры были жаркими), но сегодня systemd — стандарт де-факто в Fedora, Debian, Ubuntu, Arch, RHEL, CentOS и большинстве других дистрибутивов.
Давайте разберём его по косточкам.
Часть 1. Архитектура systemd — что происходит под капотом
1.1 PID 1 — главный процесс системы
Когда ядро Linux загружается, оно запускает самый первый пользовательский процесс с PID 1. В системах с systemd это и есть демон systemd. Он — прямой родитель всех остальных процессов в системе.
Это важно по двум причинам:
Если PID 1 упадёт — система паникует. Поэтому systemd написан максимально надёжно.
Все процессы, которые становятся «сиротами» (их родитель умер), автоматически переходят под крыло PID 1.
Ядро Linux
└── systemd (PID 1)
├── journald (логирование)
├── udevd (устройства)
├── networkd (сеть)
├── nginx.service (ваш веб-сервер)
├── postgresql.service (БД)
└── ... все остальные сервисы1.2 Ключевые компоненты системы
systemd (PID 1) Главный дирижёр. Читает юнит-файлы, строит граф зависимостей, запускает процессы в нужном порядке, следит за их состоянием через cgroups.
systemctl Ваш пульт управления. Когда вы пишете systemctl start nginx, эта утилита НЕ запускает nginx напрямую. Она отправляет сообщение по D-Bus демону systemd, который и выполняет работу. Это ключевое отличие от простого вызова скрипта.
journald Централизованная система логирования. Перехватывает stdout и stderr всех сервисов, обогащает каждую запись метаданными (PID, UID, имя юнита, хостнейм) и сохраняет в структурированном бинарном формате. Это позволяет делать сложные запросы к логам — как SQL к базе данных.
udevd Менеджер устройств. Когда вы подключаете USB-флешку, именно udevd создаёт /dev/sdb, загружает нужные модули ядра и может запустить определённый сервис.
networkd, timedated, logind Специализированные демоны для управления сетью, системным временем и пользовательскими сессиями. Они общаются с PID 1 через D-Bus.
1.3 D-Bus — как компоненты разговаривают друг с другом
D-Bus — это системная шина сообщений, аналог внутренней корпоративной почты между процессами. Вместо того чтобы процессы вызывали функции друг друга напрямую (что небезопасно), они отправляют структурированные сообщения через шину.
Практический пример: systemctl start nginx
systemctlформирует D-Bus-сообщение: «Вызови методStartUnitс аргументомnginx.service»Сообщение уходит в системную шину
Демон
systemdполучает его и выполняетВозвращает ответ через ту же шину
Это даёт безопасность (права проверяются на уровне D-Bus), гибкость (любая программа может управлять сервисами) и расширяемость.
Часть 2. Юниты — строительные блоки systemd
Юнит (unit) — это описание любого системного ресурса в виде декларативного конфигурационного файла. Думайте о нём как о «паспорте» для сервиса, сокета, таймера или точки монтирования.
2.1 Где хранятся юниты
Путь | Назначение | Приоритет |
|---|---|---|
| Юниты, установленные пакетным менеджером | Низкий |
| Ваши кастомные юниты и переопределения | Высокий |
| Временные юниты (исчезают после перезагрузки) | Высший |
Важно: Никогда не редактируйте файлы в
/usr/lib/systemd/system/напрямую — они перезапишутся при обновлении пакетов. Для изменения стандартного юнита используйтеsystemctl edit <имя>, который создаст drop-in файл в/etc/systemd/system/<имя>.d/override.conf.
2.2 Типы юнитов
.service — сервисы (самый частый тип)
Описывает демон или процесс. Именно с ним вы работаете в 90% случаев.
ini
# /etc/systemd/system/myapp.service
[Unit]
Description=My Awesome Application
After=network.target postgresql.service
Requires=postgresql.service
[Service]
Type=simple
ExecStart=/usr/bin/myapp --config /etc/myapp/config.yml
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s
User=myapp
Group=myapp
[Install]
WantedBy=multi-user.targetПараметр Type= — это важно понимать правильно:
Тип | Поведение | Когда использовать |
|---|---|---|
| systemd считает сервис запущенным сразу после старта ExecStart | Большинство современных программ |
| Программа делает fork() и завершает родительский процесс. systemd ждёт этого. | Старые Unix-демоны (nginx, apache) |
| Программа сама сигнализирует systemd через | Программы с поддержкой systemd API |
| Программа выполняется и завершается. systemd ждёт завершения. | Скрипты, одноразовые задачи |
| Сервис считается запущенным, когда занял имя на D-Bus | Демоны, использующие D-Bus |
| Запуск откладывается до завершения всех остальных задач | Фоновые задачи с низким приоритетом |
Жизненный цикл и перезапуск:
ini
[Service]
# Варианты для Restart=:
# no — не перезапускать никогда
# on-success — только при коде выхода 0
# on-failure — при любом ненулевом коде, сигнале или таймауте (самый частый выбор)
# on-abnormal — при сигнале или таймауте (не при коде выхода)
# always — перезапускать всегда (даже при systemctl stop!)
Restart=on-failure
RestartSec=5s
# Ограничение на количество перезапусков:
# Максимум 5 попыток за 30 секунд, потом сдаться
StartLimitIntervalSec=30s
StartLimitBurst=5.socket — socket-based activation (ленивый запуск)
Это одна из самых мощных и недооценённых фич systemd. Идея простая: зачем держать 20 сервисов запущенными, если большинство из них обращаются раз в час?
Socket-based activation работает так:
systemd открывает и слушает сокет (порт, Unix socket, FIFO)
Сам сервис не запущен
Приходит первое подключение
systemd запускает сервис и передаёт ему уже установленное соединение
Клиент не замечает разницы — соединение не потеряно!
ini
# /etc/systemd/system/echo.socket
[Unit]
Description=Echo Server Socket
[Socket]
ListenStream=12345
Accept=no
[Install]
WantedBy=sockets.targetini
# /etc/systemd/system/echo.service
[Unit]
Description=Echo Server Service
[Service]
Type=simple
ExecStart=/usr/local/bin/echo-server
# Сервис получит сокет через файловый дескриптор 3
StandardInput=socketАктивация: sudo systemctl enable --now echo.socket — и сервис будет запускаться автоматически при первом подключении.
.timer — замена cron с суперспособностями
Таймеры systemd мощнее cron по нескольким причинам:
Поддерживают зависимости (запустить только если работает такой-то сервис)
Логируются в journald как обычные юниты
Могут «догнать» пропущенные запуски после перезагрузки (
Persistent=true)Точность до секунды и поддержка случайных задержек для распределения нагрузки
ini
# /etc/systemd/system/backup.timer
[Unit]
Description=Daily Backup Timer
[Timer]
# Запускать каждый день в 02:30
OnCalendar=*-*-* 02:30:00
# Случайная задержка до 10 минут (не всё одновременно в 02:30!)
RandomizedDelaySec=10m
# Запустить задачу, если она была пропущена (например, система была выключена)
Persistent=true
[Install]
WantedBy=timers.targetini
# /etc/systemd/system/backup.service
[Unit]
Description=Daily Backup Job
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
User=backupАктивация: sudo systemctl enable --now backup.timer
Проверить все активные таймеры: systemctl list-timers --all
Синтаксис OnCalendar:
Выражение | Значение |
|---|---|
| Каждый день в 00:00 |
| Каждый понедельник в 00:00 |
| 1-го числа каждого месяца |
| Каждый день в 09:00 |
| По будням в 08:30 |
| 1-го и 15-го каждого месяца |
Проверить выражение: systemd-analyze calendar "Mon-Fri *-*-* 08:30:00"
.target — группы юнитов (замена runlevel)
Target — это не сервис, а точка синхронизации. Думайте об этом как о «состоянии системы», которого нужно достичь.
Target | Аналог runlevel | Значение |
|---|---|---|
| 0 | Выключение |
| 1 | Однопользовательский режим |
| 3 | Многопользовательский без GUI |
| 5 | С графическим интерфейсом |
| 6 | Перезагрузка |
bash
# Узнать текущий target (аналог текущего runlevel)
systemctl get-default
# Сменить target (аналог init 3)
sudo systemctl isolate multi-user.target
# Установить target по умолчанию
sudo systemctl set-default multi-user.target.path — реакция на события файловой системы
Аналог incron. Запускает сервис при изменениях в файловой системе.
ini
# /etc/systemd/system/watch-uploads.path
[Unit]
Description=Watch for new uploads
[Path]
# Запустить связанный .service когда появится этот файл
PathExists=/var/spool/uploads/trigger.flag
# Или мониторить директорию на изменения
DirectoryNotEmpty=/var/spool/uploads/
[Install]
WantedBy=multi-user.target2.3 Зависимости между юнитами — граф, а не очередь
Это одно из ключевых отличий systemd от SysVinit. Вместо фиксированного порядка — направленный граф зависимостей.
Директивы зависимостей:
Директива | Тип | Поведение |
|---|---|---|
| Жёсткая | Если зависимость не запустилась — этот юнит тоже не стартует и останавливается вместе с ней |
| Мягкая | Пробует запустить зависимость, но если та упадёт — не останавливается |
| Очень жёсткая | Как Requires, но юнит останавливается если зависимость остановится в любой момент |
| Односторонняя | Останавливается/перезапускается вместе с зависимостью, но не запускается вместе с ней |
| Конфликт | Не может работать одновременно с указанным юнитом |
Директивы порядка:
Директива | Поведение |
|---|---|
| Этот юнит запускается ПОСЛЕ указанного |
| Этот юнит запускается ДО указанного |
Важный нюанс:
After=иBefore=задают только порядок, но не зависимость! Если вы напишете толькоAfter=postgresql.service, но неRequires=postgresql.service, то ваш сервис стартует после PostgreSQL, но запустится даже если PostgreSQL упал. Обычно нужно использовать оба.
ini
[Unit]
# Правильная комбинация: сначала БД, потом мы, и мы не работаем без БД
After=postgresql.service
Requires=postgresql.serviceЧасть 3. cgroups — почему systemd знает всё о ваших процессах
3.1 Проблема, которую решают cgroups
Представьте: nginx запущен. Он форкает 4 воркера. Один воркер форкает ещё процесс для CGI. Тот форкает что-то ещё. Итого 10 процессов, и все они «принадлежат» nginx, но в SysVinit это было невозможно отследить.
Control Groups (cgroups) — механизм ядра Linux, который позволяет объединять процессы в иерархические группы и управлять ими совместно.
Systemd автоматически создаёт cgroup для каждого сервиса. Все дочерние процессы — внутри этой группы. Всегда.
/sys/fs/cgroup/
├── system.slice/
│ ├── nginx.service/ ← все процессы nginx здесь
│ │ ├── pid: 1234 (master)
│ │ ├── pid: 1235 (worker 1)
│ │ ├── pid: 1236 (worker 2)
│ │ └── pid: 1237 (cache loader)
│ ├── postgresql.service/ ← и postgres здесь
│ └── redis.service/
└── user.slice/
└── user-1000.slice/ ← процессы пользователя3.2 Что даёт cgroup на практике
Точный kill без зомби-процессов: При systemctl stop nginx systemd отправляет сигнал всей cgroup — умирают все 10 процессов, включая те, о которых вы не знали. Больше никаких «phantom workers».
Мониторинг:
bash
# Показать дерево процессов cgroup сервиса
systemd-cgls /system.slice/nginx.service
# Вывод:
# /system.slice/nginx.service
# └─ 1234 /usr/sbin/nginx -g daemon off;
# ├─ 1235 nginx: worker process
# ├─ 1236 nginx: worker process
# └─ 1237 nginx: cache loader process
# Мониторинг ресурсов в реальном времени (как top, но для cgroups)
systemd-cgtop3.3 Ограничение ресурсов через юнит-файлы
Это магия. Вместо сложных настроек cgroups вручную — просто добавляете строки в секцию [Service]:
ini
[Service]
# === ПАМЯТЬ ===
# Мягкий лимит: systemd начнёт агрессивно освобождать память
MemoryHigh=400M
# Жёсткий лимит: OOM Killer убьёт процесс если превысит
MemoryMax=512M
# Гарантированная память (не будет отдана другим)
MemoryMin=100M
# === CPU ===
# 50% от одного ядра
CPUQuota=50%
# Или: вес CPU (1-10000, default=100)
CPUWeight=200
# === ДИСК (I/O) ===
# Ограничение чтения/записи для конкретного устройства
IOReadBandwidthMax=/dev/sda 50M
IOWriteBandwidthMax=/dev/sda 20M
# === СЕТЬ (через IP accounting) ===
IPAccounting=yes
IPAddressAllow=192.168.0.0/24
IPAddressDeny=anyПроверка текущих лимитов:
bash
# Посмотреть параметры cgroup напрямую в файловой системе
cat /sys/fs/cgroup/system.slice/nginx.service/memory.max
# 536870912 (512 МБ в байтах)
# Или через systemctl
systemctl show nginx.service | grep -E 'Memory|CPU|IO'Часть 4. journald — логи как база данных
4.1 Почему journald лучше текстовых логов
Обычный syslog — это текстовый файл. Хочешь найти все ошибки nginx за последний час? Пишешь grep "error" /var/log/nginx/error.log | grep "$(date +%b\ %d)" и молишься.
journald — структурированное хранилище с индексами. Каждая запись — не строчка текста, а объект с полями:
_SYSTEMD_UNIT=nginx.service ← какой сервис
_PID=1234 ← какой процесс
_UID=www-data ← от какого пользователя
_HOSTNAME=web-01 ← на каком хосте
PRIORITY=3 ← уровень важности (err)
MESSAGE=connection refused... ← само сообщение
_SOURCE_REALTIME_TIMESTAMP=... ← точное время4.2 Полное руководство по journalctl
bash
# === БАЗОВЫЕ ЗАПРОСЫ ===
# Все логи конкретного сервиса
sudo journalctl -u nginx.service
# Последние 50 строк
sudo journalctl -u nginx.service -n 50
# Следить в реальном времени (как tail -f)
sudo journalctl -u nginx.service -f
# С определённого момента
sudo journalctl -u nginx.service --since "2024-01-15 10:00:00"
sudo journalctl -u nginx.service --since "1 hour ago"
sudo journalctl -u nginx.service --since today
sudo journalctl -u nginx.service --since yesterday --until "2024-01-14 23:59:59"
# === ФИЛЬТРАЦИЯ ПО УРОВНЮ ВАЖНОСТИ ===
# 0=emerg, 1=alert, 2=crit, 3=err, 4=warning, 5=notice, 6=info, 7=debug
sudo journalctl -p err # только err
sudo journalctl -p err..warning # от err до warning
sudo journalctl -u nginx -p warning # предупреждения nginx
# === ФИЛЬТРАЦИЯ ПО ЗАГРУЗКЕ ===
sudo journalctl -b # текущая загрузка
sudo journalctl -b -1 # предыдущая загрузка
sudo journalctl -b -2 # позапрошлая загрузка
sudo journalctl --list-boots # список всех загрузок
# === ФОРМАТЫ ВЫВОДА ===
sudo journalctl -u nginx -o json # JSON (для парсинга)
sudo journalctl -u nginx -o json-pretty # JSON с форматированием
sudo journalctl -u nginx -o verbose # Все поля записи
sudo journalctl -u nginx -o cat # Только текст сообщений
# === ПРОДВИНУТЫЕ ЗАПРОСЫ ===
# Логи конкретного процесса
sudo journalctl _PID=1234
# Логи от конкретного пользователя
sudo journalctl _UID=1000
# Комбинирование условий (OR)
sudo journalctl _SYSTEMD_UNIT=nginx.service + _SYSTEMD_UNIT=php-fpm.service
# Экспорт в файл
sudo journalctl -u nginx --since today -o json > nginx-today.json
# === УПРАВЛЕНИЕ ЖУРНАЛОМ ===
# Размер журнала на диске
sudo journalctl --disk-usage
# Очистка старых логов (оставить только за последние 2 недели)
sudo journalctl --vacuum-time=2weeks
# Очистка до определённого размера
sudo journalctl --vacuum-size=500M4.3 Настройка journald
ini
# /etc/systemd/journald.conf
[Journal]
# Максимальный размер журнала на диске
SystemMaxUse=1G
# Максимальный размер одного файла журнала
SystemMaxFileSize=100M
# Хранить журналы не дольше
MaxRetentionSec=1month
# Сжатие (по умолчанию включено)
Compress=yes
# Перенаправить в syslog (для совместимости)
ForwardToSyslog=no
# Уровень логирования по умолчанию
MaxLevelStore=debug
MaxLevelSyslog=warningПосле изменения: sudo systemctl restart systemd-journald
Часть 5. Практика — реальные сценарии
5.1 Создание production-ready сервиса с нуля
Задача: создать сервис для Go-приложения с полной изоляцией и автоматическим перезапуском.
ini
# /etc/systemd/system/api-server.service
[Unit]
Description=API Server
Documentation=https://github.com/company/api-server
After=network.target
Wants=network-online.target
After=network-online.target
# Если зависит от БД:
Requires=postgresql.service
After=postgresql.service
[Service]
Type=notify
# Путь к бинарнику
ExecStart=/usr/local/bin/api-server
# Путь к конфигу через переменную окружения
EnvironmentFile=/etc/api-server/env
# Или напрямую:
Environment="PORT=8080"
Environment="LOG_LEVEL=info"
# Перезапуск
Restart=on-failure
RestartSec=5s
StartLimitIntervalSec=60s
StartLimitBurst=3
# Пользователь и группа
User=api
Group=api
# Рабочая директория
WorkingDirectory=/opt/api-server
# === БЕЗОПАСНОСТЬ ===
# Запрет повышения привилегий
NoNewPrivileges=yes
# Изолированный /tmp
PrivateTmp=yes
# Только чтение для /usr, /boot, /etc
ProtectSystem=strict
# Запрет доступа к домашним директориям
ProtectHome=yes
# Изолированная сеть для системных вызовов
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
# Список разрешённых системных вызовов
SystemCallFilter=@system-service
# Разрешить запись только в эти директории
ReadWritePaths=/var/lib/api-server /var/log/api-server
# === РЕСУРСЫ ===
MemoryMax=512M
CPUQuota=200%
# Ограничение открытых файлов
LimitNOFILE=65536
[Install]
WantedBy=multi-user.targetПрименение:
bash
sudo systemctl daemon-reload
sudo systemctl enable --now api-server.service
sudo systemctl status api-server.service5.2 Drop-in файлы — переопределение без изменения оригинала
Золотое правило: никогда не редактируйте файлы в /usr/lib/systemd/system/. Используйте drop-in файлы.
bash
# Удобный способ — systemctl edit сам создаст файл
sudo systemctl edit nginx.serviceСоздастся файл /etc/systemd/system/nginx.service.d/override.conf:
ini
[Service]
# Добавим лимит памяти к стандартному nginx
MemoryMax=256M
# Переопределим тип перезапуска
Restart=always
# Добавим переменную окружения
Environment="NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx"bash
# После сохранения:
sudo systemctl daemon-reload
sudo systemctl restart nginx.service
# Посмотреть итоговую конфигурацию (оригинал + drop-ins)
sudo systemctl cat nginx.service5.3 Анализ и оптимизация времени загрузки
bash
# Общее время загрузки
systemd-analyze
# Startup finished in 2.134s (kernel) + 8.643s (userspace) = 10.777s
# Топ «тормозов» при загрузке
systemd-analyze blame
# 4.123s NetworkManager-wait-online.service
# 2.456s plymouth-quit-wait.service
# 1.234s dev-sda1.device
# 0.987s apparmor.service
# Критический путь загрузки — что тормозит конкретный target
systemd-analyze critical-chain graphical.target
# Визуальная диаграмма в SVG (откройте в браузере!)
systemd-analyze plot > boot-plot.svg
# Проверить юнит-файл на ошибки
systemd-analyze verify /etc/systemd/system/myapp.serviceЧастые причины медленной загрузки и как их лечить:
Проблема | Симптом | Решение |
|---|---|---|
| 20-30 секунд ожидания сети |
|
Сервис висит на старте | Долгий timeout | Проверить |
Много последовательных зависимостей | Длинный critical chain | Заменить |
5.4 Диагностика падающего сервиса — пошаговый алгоритм
bash
# Шаг 1: Статус сервиса
sudo systemctl status myapp.service
# Ищем: статус (failed/active), последние строки лога, код выхода
# Шаг 2: Последние логи с подробными метаданными
sudo journalctl -u myapp.service -n 100 --no-pager
# Шаг 3: Логи с момента последней загрузки (для проблем при старте)
sudo journalctl -u myapp.service -b
# Шаг 4: Все ошибки в системе в момент падения
sudo journalctl -p err --since "10 min ago" --no-pager
# Шаг 5: Проверить зависимости
systemctl list-dependencies myapp.service
# Все зависимости должны быть зелёными
# Шаг 6: Запустить вручную под тем же пользователем (для воспроизведения)
sudo -u myapp /usr/local/bin/myapp --config /etc/myapp/config.yml
# Шаг 7: Посмотреть все переменные окружения сервиса
sudo systemctl show myapp.service -p Environment
# Шаг 8: Проверить права доступа к файлам
sudo systemctl cat myapp.service | grep -E 'ExecStart|WorkingDirectory|User'
sudo ls -la /usr/local/bin/myappЧасть 6. Продвинутые техники
6.1 Шаблонные юниты — один файл для многих экземпляров
Если нужно запустить один и тот же сервис с разными параметрами (например, несколько воркеров), используйте шаблоны.
ini
# /etc/systemd/system/worker@.service
# Обратите внимание на @ в имени файла!
[Unit]
Description=Worker Instance %i
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/worker --id=%i --config=/etc/worker/config.yml
User=worker
Restart=on-failure
[Install]
WantedBy=multi-user.targetЗапуск нескольких экземпляров:
bash
# %i заменится на значение после @
sudo systemctl start worker@1.service
sudo systemctl start worker@2.service
sudo systemctl start worker@3.service
# Или всех сразу:
sudo systemctl enable worker@{1..5}.service
sudo systemctl start worker@{1..5}.service
# Посмотреть все запущенные экземпляры
systemctl list-units 'worker@*'6.2 Временные сервисы через systemd-run
bash
# Запустить команду как временный сервис (исчезнет после завершения)
sudo systemd-run --unit=my-task /usr/bin/python3 /opt/scripts/heavy_task.py
# С ограничением ресурсов
sudo systemd-run --unit=cpu-heavy --property=CPUQuota=50% --property=MemoryMax=256M \
/usr/bin/python3 /opt/scripts/heavy_task.py
# Следить за прогрессом
journalctl -u my-task -f6.3 Полезные команды, о которых мало кто знает
bash
# Проверить юнит-файл на синтаксические ошибки ДО применения
systemd-analyze verify /etc/systemd/system/myapp.service
# Показать все переопределения (drop-in файлы) для сервиса
systemctl cat nginx.service
# Показать все свойства юнита
systemctl show nginx.service
# Показать конкретное свойство
systemctl show nginx.service -p MainPID
systemctl show nginx.service -p MemoryCurrent
# Перезагрузить конфиги без daemon-reload (для drop-in файлов)
sudo systemctl daemon-reload
# Перечитать конфиги всех сервисов (более мягкий вариант)
sudo systemctl reload-or-restart nginx.service
# Узнать, какой пакет установил юнит
systemctl cat nginx.service | head -1
# # /lib/systemd/system/nginx.service
dpkg -S /lib/systemd/system/nginx.service # Debian/Ubuntu
rpm -qf /lib/systemd/system/nginx.service # RHEL/Fedora
# Блокировка: сервис не запустится даже вручную
sudo systemctl mask dangerous-service.service
# Разблокировка
sudo systemctl unmask dangerous-service.serviceШпаргалка — все команды в одном месте
Управление сервисами
Задача | Команда |
|---|---|
Запустить |
|
Остановить |
|
Перезапустить |
|
Перечитать конфиг (без остановки) |
|
Reload или restart |
|
Статус |
|
Включить автозапуск |
|
Выключить автозапуск |
|
Включить И запустить |
|
Заблокировать навсегда |
|
Просмотр состояния
Задача | Команда |
|---|---|
Все запущенные сервисы |
|
Все упавшие |
|
Проверить автозапуск |
|
Проверить активность |
|
Дерево зависимостей |
|
Кто зависит от этого |
|
Все таймеры |
|
Логи (journalctl)
Задача | Команда |
|---|---|
Логи сервиса |
|
Последние N строк |
|
В реальном времени |
|
За текущую загрузку |
|
Только ошибки |
|
С определённого времени |
|
Размер журнала |
|
Очистить старые |
|
Диагностика производительности
Задача | Команда |
|---|---|
Время загрузки |
|
Что грузилось дольше всех |
|
Критический путь |
|
Визуальная диаграмма |
|
Проверить юнит-файл |
|
Дерево cgroups |
|
Ресурсы cgroups в реальном времени |
|
Заключение
Systemd — это не монстр, которого стоит бояться. Это мощный инструмент, понимание которого делает вас значительно эффективнее как системного администратора или разработчика. Несколько ключевых идей, которые стоит унести из этой статьи:
Юниты — декларативные описания ресурсов. Пишите их правильно, используя все доступные настройки безопасности.
cgroups — системd всегда знает, где ваши процессы. Используйте это для мониторинга и ограничения ресурсов.
journald — это база данных, а не текстовый файл. Учитесь делать правильные запросы.
Drop-in файлы — никогда не редактируйте оригинальные юнит-файлы из пакетов.
systemd-analyze — ваш первый инструмент при проблемах с загрузкой.
Create an account or sign in to leave a review
There are no reviews to display.