Введение / Зачем это нужно
Systemd — это современная система инициализации и менеджер служб для большинства дистрибутивов Linux. Создание собственного сервиса (демона) позволяет автоматически запускать ваши скрипты или программы при загрузке системы, управлять их жизненным циклом (старт, стоп, перезагрузка), централизованно логировать вывод и обеспечивать восстановление при сбоях. Это стандартный и надёжный способ развёртывания фоновых задач в Linux.
После выполнения этого гайда вы сможете создать работающий сервис для любой исполняемой программы (Python-скрипт, bash-скрипт, бинарный файл), который будет:
- Автоматически стартовать при загрузке ОС.
- Корректно завершаться при выключении.
- Писать логи в
journald(системный журнал). - Перезапускаться при аварийном завершении.
Требования / Подготовка
Перед началом убедитесь, что:
- У вас есть доступ к терминалу с правами sudo (для системных сервисов) или доступ к домашней директории (для пользовательских).
- На системе установлен systemd (актуально для всех современных дистрибутивов: Ubuntu 22.04+, Debian 11+, CentOS 8/RHEL 8+, Fedora 35+).
- Исполняемый файл или скрипт, который нужно сервисировать, уже готов, протестирован вручную и имеет права на выполнение (
chmod +x /путь/к/файлу). - Вы знаете абсолютный путь к этому исполняемому файлу.
Шаг 1: Подготовка исполняемого скрипта или программы
Предположим, у вас есть простой bash-скрипт для мониторинга дискового пространства, который должен работать в фоне. Он уже создан и расположен по пути /opt/scripts/disk_monitor.sh.
#!/bin/bash
# Пример скрипта /opt/scripts/disk_monitor.sh
while true; do
DATE=$(date '+%Y-%m-%d %H:%M:%S')
df -h / | tail -n1 | awk '{print "ROOT: " $5 " used"}' >> /var/log/disk_monitor.log
sleep 300
done
Проверьте его работоспособность вручную:
sudo chmod +x /opt/scripts/disk_monitor.sh
sudo /opt/scripts/disk_monitor.sh
Нажмите Ctrl+C для тестовой остановки. Убедитесь, что в /var/log/disk_monitor.log появляются записи.
Шаг 2: Создание unit-файла
Создайте файл сервиса. Для системного сервиса (работающего от root или указанного пользователя) используйте /etc/systemd/system/.
sudo nano /etc/systemd/system/disk-monitor.service
💡 Совет: Имя файла обычно совпадает с именем сервиса. Используйте латинские буквы, цифры, дефисы. Точка в имени не требуется, но допустима.
Шаг 3: Написание базовой конфигурации Unit и Service
Вставьте в редактор следующую конфигурацию. Она покрывает большинство базовых сценариев.
[Unit]
Description=Сервис мониторинга свободного места на корневом разделе
Documentation=man:df(1)
After=network.target
[Service]
Type=simple
ExecStart=/opt/scripts/disk_monitor.sh
Restart=on-failure
RestartSec=10
User=root
Group=root
[Install]
WantedBy=multi-user.target
Разбор секций:
[Unit]— метаданные и зависимости.Description— краткое описание сервиса (показывается вsystemctl status).After— указывает, что сервис должен стартовать после включения сети (network.target). Для не-сетевых сервисов можно убрать или указатьlocal-fs.target(после монтирования локальных ФС).
[Service]— основная конфигурация процесса.Type=simple(по умолчанию) — systemd считает, что процесс, указанный вExecStart, является основным и работает в foreground. Подходит для большинства скриптов и современных программ.ExecStart— абсолютный путь к команде/скрипту для запуска. Все аргументы указываются здесь.Restart=on-failure— автоматически перезапускать сервис, если он завершился с ненулевым кодом возврата.RestartSec=10— ждать 10 секунд перед перезапуском.User/Group— от имени какой пользователя/группы запускать процесс. Безопаснее указывать не-root пользователя (например,User=monitoruser), если в этом нет необходимости. Для системных утилит может потребоватьсяroot.
[Install]— инструкции дляsystemctl enable.WantedBy=multi-user.target— создаст симлинк в/etc/systemd/system/multi-user.target.wants/, что означает "запускать при загрузке в многопользовательском режиме (стандартный)". Для графических сервисов может использоватьсяgraphical.target.
Сохраните файл (Ctrl+O, Enter) и закройте редактор (Ctrl+X).
Шаг 4: Настройка автозагрузки и инициализация
После создания или изменения unit-файла обязательно выполните команду перезагрузки конфигурации systemd:
sudo systemctl daemon-reload
Теперь включите сервис в автозагрузку (создаст симлинк):
sudo systemctl enable disk-monitor.service
Вывод: Created symlink /etc/systemd/system/multi-user.target.wants/disk-monitor.service → /etc/systemd/system/disk-monitor.service.
Шаг 5: Запуск и проверка статуса
Запустите сервис вручную:
sudo systemctl start disk-monitor.service
Проверьте его статус:
sudo systemctl status disk-monitor.service
Ожидаемый вывод (упрощённо):
● disk-monitor.service - Сервис мониторинга свободного места на корневом разделе
Loaded: loaded (/etc/systemd/system/disk-monitor.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2026-02-15 14:30:00 MSK; 5s ago
Main PID: 12345 (bash)
Tasks: 1 (limit: 4915)
Memory: 1.2M
CGroup: /system.slice/disk-monitor.service
└─12345 /bin/bash /opt/scripts/disk_monitor.sh
Ключевые строки:
Loaded— файл загружен,enabled— включён в автозагрузку.Active: active (running)— сервис работает.Main PID— PID основного процесса.CGroup— cgroup, в который помещён процесс.
Шаг N: Дополнительные операции управления
Теперь вы можете управлять сервисом стандартными командами:
- Остановить:
sudo systemctl stop disk-monitor.service - Перезапустить:
sudo systemctl restart disk-monitor.service(используйте, если меняли конфиг). - Перезагрузить:
sudo systemctl reload disk-monitor.service(если сервис поддерживает SIGHUP для перечитывания конфига без полной остановки). - Показать логи:
sudo journalctl -u disk-monitor.service -f(-f— следить за новыми записями в реальном времени). - Проверить конфигурацию на синтаксис:
sudo systemctl daemon-reload(выполняется автоматически приenable/start, но полезно после ручного редактирования файла).
Проверка результата
- Автозапуск: Перезагрузите систему (
sudo reboot). После входа проверьте статус сервиса:systemctl status disk-monitor.service. Он должен бытьactive (running). - Логирование: Убедитесь, что логи пишутся:
sudo tail -f /var/log/disk_monitor.logили через journald:sudo journalctl -u disk-monitor.service. - Автоматическое восстановление: Принудительно завершите процесс (например,
sudo kill <PID>изstatus). Через несколько секунд проверьте статус снова — systemd должен его перезапустить.
Возможные проблемы
Проблема: systemctl status показывает failed (Result: exit-code).
Решение: Посмотрите детали ошибки в том же выводе status (строка ...). Чаще всего это:
- Неправильный путь в
ExecStart. Убедитесь, что путь абсолютный и файл существует. - Нет прав на выполнение.
sudo chmod +x /путь/к/скрипту. - Ошибка внутри скрипта. Запустите скрипт вручную от того же пользователя (
sudo -u <user> /путь/к/скрипту) и проверьте вывод. - Зависимости. Если скрипту нужен доступ к сети или смонтированным дискам, проверьте
After=иRequires=в секции[Unit].
Проблема: Сервис не включается в автозагрузку (systemctl is-enabled возвращает disabled).
Решение: Выполните sudo systemctl enable disk-monitor.service ещё раз после daemon-reload. Убедитесь, что в [Install] есть секция WantedBy= или RequiredBy=.
Проблема: Логи сервиса пустые в journalctl.
Решение: По умолчанию systemd перехватывает stdout/stderr. Если скрипт пишет напрямую в файл (как в примере), в journald его вывод не попадёт. Это нормально. Для логирования через journald уберите перенаправление в файл из скрипта, а для постоянного хранения логов настройте journalctl с ротацией или используйте StandardOutput=append:/var/log/disk_monitor.log в секции [Service].
Проблема: Сервис запускается, но сразу завершается.
Решение: Это часто бывает при Type=simple, если основной процесс завершается. Для долгоживущих скриптов убедитесь, что в них есть бесконечный цикл или ожидание (sleep). Если программа сама демонизируется (fork), может потребоваться Type=forking и PIDFile=/var/run/имя.pid. Но для простых скриптов с циклом Type=simple — правильный выбор.