Как создать systemd‑сервис в Linux

systemd — это менеджер служб в большинстве современных дистрибутивов Linux. Служба (service) — это юнит программы, który обычно работает в фоне. Службы обычно запускаются автоматически при старте системы и могут работать без вмешательства пользователя.
Если вам нужно, чтобы задача или программа запускались при каждой загрузке системы, имеет смысл создать собственный systemd‑сервис. В этой статье подробно показано, как создать, настроить, включить и отладить пользовательский сервис.
Куда помещается файл сервиса и базовая структура
Каждый systemd‑сервис описывается единым юнит‑файлом с расширением .service, обычно в каталоге /etc/systemd/system/. Юнит-файл состоит из трёх обязательных блоков: [Unit], [Service] и [Install]. Рассмотрим их на примере реального файла.
Кратко:
- [Unit] — метаданные и зависимости.
- [Service] — параметры запуска процесса.
- [Install] — параметры включения в таргеты при enable/disable.
Перед созданием файла полезно понять структуру. Ниже — базовый шаг для создания пустого файла (выполняется с root‑привилегиями):
sudo touch /etc/systemd/system/.service Затем откройте файл в удобном редакторе (nano, vim и т. п.) и начинайте наполнять секции.
Пример: сервис, запускающий nmap каждые 30 секунд
В демонстрационных целях создадим сервис, который запускает nmap и сохраняет вывод в файл каждые 30 секунд. Ниже — пример юнит‑файла:
[Unit]
Description=Демонстрация пользовательского nmap‑сервиса
After=network.target
[Service]
Type=simple
User=root
ExecStart=/usr/bin/nmap -sS -O -oN /home/<пользователь>/results.txt localhost
Restart=always
RestartSec=30
[Install]
WantedBy=multi-user.targetСохранив этот файл как /etc/systemd/system/custom-nmap.service, выполните следующие команды для активации:
sudo systemctl daemon-reload
sudo systemctl enable custom-nmap.service
sudo systemctl start custom-nmap.service
sudo systemctl status custom-nmap.serviceВ результате сервис будет перезапускаться каждые 30 секунд, а результаты nmap запишутся в указанный файл.
Разбор ключевых директив
- Description — читаемое описание сервиса.
- After=network.target — указывает, что сервис должен стартовать после достижения network.target. Это не жёсткая зависимость, а порядок запуска.
- Type=simple — тип процесса. simple значит: systemd считает процесс главным и не ожидает форк‑процедур.
- ExecStart — абсолютный путь к исполняемой команде с аргументами.
- Restart=always — перезапускать сервис при любом завершении.
- RestartSec=30 — задержка перед перезапуском, в секундах.
- User=root — сервис запустится под указанным пользователем.
- WantedBy=multi-user.target — сервис будет включён в target multi-user при enable.
Важно: используйте абсолютные пути и проверяйте права доступа. Если команда требует окружения (переменные PATH и др.), явно указывайте их в ExecStart или используйте Environment/EnvironmentFile.
Частые ошибки и как их фиксить
- Файл не обнаружен после правки
- После изменения юнита всегда выполняйте sudo systemctl daemon-reload.
- Служба не запускается — permission denied
- Проверьте права на исполняемый файл и файлы, куда пишется вывод. Если сервис запускается от root, это обычно не проблема, но запуск от непривилегированного пользователя требует доступа.
- Неправильные относительные пути
- Используйте абсолютные пути в ExecStart и в путях в конфигурации.
- Служба быстро выходит из состояния активна, systemd не перезапускает
- Проверьте Type. Многие демоны форкаются; для них нужен Type=forking и правильный PIDFile.
- SELinux/AppArmor блокирует запуск
- Посмотрите логи ядра и утилиты аудита, временно отключите профиль или добавьте правила.
- Ожидания зависимостей
- After= не гарантирует наличия ресурса. Если нужен жёсткий порядок запуска, добавьте Wants= или Requires=.
Отладка: полезные команды
- systemctl status <имя>.service — статус, последние строки журнала.
- journalctl -u <имя>.service — полный журнал юнита.
- journalctl -b — журнал текущей загрузки.
- sudo systemctl daemon-reload — перечитать юнит‑файлы.
- sudo systemctl restart <имя>.service — перезапустить службу.
- sudo systemctl disable –now <имя>.service — отключить и остановить.
- sudo systemctl mask <имя>.service — полностью заблокировать запуск.
Когда systemd‑сервис — не лучшая идея (альтернативы)
- Cron / crontab — для запуска заданий по расписанию (каждую минуту, час, день). Проще для одноразовых задач по времени.
- systemd timers — встроенная альтернатива cron с теми же удобствами systemd. Лучше для повторяющихся задач, которые управляются как таймеры.
- Anacron — для машин, которые не работают постоянно (выполняет задания при следующем включении).
- Docker restart policies — если задача запускается внутри контейнера, используйте политику рестарта контейнера.
Короткая рекомендация: для периодических задач, привязанных к systemd, рассмотрите systemd timer вместо постоянного сервиса, запускающегося в петле.
Мини‑методология: как проектировать надежный сервис (шаблон процесса)
- Определите требования: пользователь, права, порядок запуска, ожидания выхода.
- Напишите и протестируйте команду вручную в интерактивной сессии.
- Создайте юнит в /etc/systemd/system/ с четкими путями и классификацией Type.
- Добавьте безопасность: User, CapabilityBoundingSet, PrivateTmp, NoNewPrivileges.
- Выполните daemon-reload, затем enable и start в тестовой среде.
- Наблюдайте через journalctl; при успехе продвигайте в продакшен.
- Создайте инструкцию отката и чеклист безопасности.
Роль‑ориентированные чеклисты
Чеклист для администратора:
- Проверил абсолютные пути в ExecStart.
- Выполнил systemctl daemon-reload.
- Проверил журналы через journalctl -u.
- Настроил права и SELinux/AppArmor профиль.
- Добавил unit в конфигурацию резервного мониторинга.
Чеклист для разработчика:
- Сценарий запуска работает вручную.
- Логи читаемы и структурированы.
- Выходные файлы пишутся в защищённые каталоги.
- Сервис корректно обрабатывает SIGTERM/SIGINT.
Безопасность и жёсткие ограничения
По умолчанию сервис может запускаться с привилегиями root. Это повышает риски. Рекомендации по жёсткой изоляции и ограничению прав:
- По возможности запускайте от непривилегированного пользователя (User=).
- Используйте CapabilityBoundingSet= чтобы ограничить системные возможности.
- Установите NoNewPrivileges=yes чтобы предотвратить повышение привилегий.
- Примените PrivateTmp=yes и ProtectSystem=strict для уменьшения поверхности атаки.
- Ограничьте доступ к сети через NetworkNamespace или Firewall.
- Используйте ReadOnlyPaths= для монтирования системных директорий только для чтения.
Пример безопасной секции Service:
[Service]
Type=simple
User=svc-nmap
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=full
CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN
ExecStart=/usr/bin/nmap -sS -O -oN /var/lib/serviceresults/results.txt localhost
Restart=on-failure
RestartSec=30Важно: перечисленные параметры сильно помогают снизить риск, но требуют тестирования, чтобы они не блокировали легитимную работу сервиса.
Критерии приёмки
- Сервис корректно запускается командой systemctl start и не падает в течение 5 минут при стандартной нагрузке.
- Все файлы вывода доступны только нужным пользователям и имеют права, соответствующие политике компании.
- При stop/disable сервис останавливается и не перезапускается автоматически.
- Логи содержат достаточную информацию для расследования инцидентов.
Откат и аварийная остановка
Шаги для быстрой остановки и отключения сервиса:
sudo systemctl stop <имя>.service
sudo systemctl disable <имя>.service
sudo systemctl mask <имя>.service
sudo systemctl daemon-reloadMask запрещает запуск даже зависимостям. Для восстановления используйте unmask и enable.
Decision flow: запуск сервиса или таймера
flowchart TD
A[Нужно запускать задачу] --> B{Периодичность}
B -->|Непрерывно| C[systemd‑service]
B -->|Раз в X времени| D{Высокая точность?}
D -->|Да| E[systemd‑timer]
D -->|Нет| F[cron / anacron]
C --> G[Оценить безопасность и изоляцию]
E --> G
F --> GКогда systemd‑сервис не подойдёт
- Нужно точное планирование в секундах с высокой надёжностью на уровне часов — рассмотрите systemd timer или внешние планировщики.
- Процессы с интенсивными временными паузами лучше запускать через cron или специализированные очереди заданий.
Практические советы и жесткие рекомендации
- Всегда тестируйте сервис в тестовой среде до продакшена.
- Логи делайте ротационными (logrotate) и ограничьте размер.
- Не храните чувствительные данные в незашифрованных файлах, к которым доступна служба.
- Документируйте все написанные юниты и связанные таймеры/скрипты.
Заключение
Создание systemd‑сервиса — удобный и мощный способ запускать автозапускаемые фоновые задачи в Linux. Начните с простого юнита, убедитесь в правильности путей и прав, добавьте ограничения безопасности и наблюдение. Если задача периодическая по расписанию, рассмотрите systemd timers как более корректную альтернативу. Воспользуйтесь приведёнными checklist’ами и командами для отладки.
Краткая сводка:
- Файл юнита хранится в /etc/systemd/system/*.service.
- Всегда используйте daemon-reload после изменений.
- Для безопасности ограничивайте привилегии сервиса.
- Альтернативы: cron, anacron, systemd timer.
Если нужно, я могу помочь подготовить конкретный unit‑файл под вашу задачу, проверить его на потенциальные уязвимости и предложить тестовый план развертывания.
Похожие материалы
Как установить шрифты на Windows, Linux и macOS
Исправление Machine Check Exception в Windows
Как удалить историю браузера на Android
Отключить Google Suggest, Instant и Preview
7 лучших сайтов для изучения Photoshop