Гид по технологиям

Управление приложениями через Systemd: создание и настройка пользовательских сервисов

• 6 min read • Linux • Обновлено 24 Nov 2025
Systemd: как создать и настроить кастомный сервис
Systemd: как создать и настроить кастомный сервис

Человек работает за компьютером с открытым терминалом и примером файла unit Systemd.

Systemd — это мощная и гибкая init-система для Linux. Она управляет запуском программ, распределением системных ресурсов и состоянием системы в целом. В этой статье мы разберёмся, как управлять вашими приложениями с помощью Systemd через создание и настройку пользовательских unit-файлов в Ubuntu (и совместимых дистрибутивах).

Что такое unit-файл Service в Systemd

Unit-файл сервиса — это обычный текстовый файл, содержащий инструкции для Systemd: описание программы, команды запуска, зависимости и правила автозапуска. Файл разбит на секции Unit, Service и Install:

  • Unit — метаданные и зависимости (когда запускать);
  • Service — как и где запускать сервис (команды ExecStart, поведение при перезапуске и т. п.);
  • Install — подключение к таргетам (в какой конфигурации включать сервис).

Каждый демон в Systemd обычно имеет свой unit-файл. Например, OpenSSH использует ssh.service, который лежит в /etc/systemd/system или /lib/systemd/system в Debian/Ubuntu.

Терминал с примером unit-файла OpenSSH, показывающий секции и зависимости.

Короткое определение: unit-файл — это декларация того, как Systemd должен управлять конкретным процессом.

Создание system-level кастомного сервиса

Когда нужен system-level сервис:

  • команда требует привилегий root;
  • сервис должен стартовать до входа пользователя;
  • нужно, чтобы сервис был управляем системой (restart, dependencies).

Пример: автозапуск игрового сервера после перезагрузки или фоновой службы, работающей под root.

  1. Создайте unit-файл в домашнем каталоге (временный шаг):
nano ~/my-system-app.service
  1. Вставьте минимальную конфигурацию (это корректный и простой unit-файл):
[Unit]
Description=My First Service
After=network.target

[Service]
Type=simple
ExecStart=/path/to/bin
Restart=always

[Install]
WantedBy=multi-user.target

Пояснения: замените Description и, важнее, ExecStart на полный путь до исполняемого файла вашего приложения.

Терминал с примером простого unit-файла для system-level сервиса.

  1. Сохраните файл, затем переместите его в системную директорию сервисов:
sudo cp ./my-system-app.service /etc/systemd/system/
  1. Перезагрузите конфигурацию демона Systemd:
sudo systemctl daemon-reload
  1. Запустите сервис и проверьте его статус:
sudo systemctl start my-system-app.service
systemctl status my-system-app.service

Если нужны автозапуск при загрузке: sudo systemctl enable my-system-app.service.

Терминал, показывающий успешный запуск и статус кастомного системного сервиса.

Создание user-level кастомного сервиса

User-level сервисы (rootless) полезны, когда вы хотите, чтобы пользователь мог самостоятельно запускать демон без прав root. Такие сервисы интегрируются с сессией пользователя и запускаются при его входе (в зависимости от таргета).

  1. Создайте unit-файл в домашней папке:
nano ~/my-user-app.service
  1. Пример минимального user unit:
[Unit]
Description=My First User Service
After=graphical-session.target

[Service]
Type=simple
ExecStart=/path/to/bin

[Install]
WantedBy=default.target

Убедитесь, что пользователь имеет доступ к исполняемому файлу, указанному в ExecStart.

Терминал с выделением скрипта пользователя и прав доступа обычного пользователя.

  1. Создайте локальную папку для user unit-файлов и скопируйте туда файл:
mkdir -p ~/.config/systemd/user/
cp ./my-user-app.service ~/.config/systemd/user/
  1. Перезагрузите пользовательский демон и запустите сервис:
systemctl daemon-reload --user
systemctl --user start my-user-app.service
systemctl --user status my-user-app.service

Терминал, показывающий, что пользовательский сервис распознан systemctl --user.

Важно: user-сервисы привязаны к пользовательской сессии. Если сессия завершается, поведение сервиса зависит от конфигурации и Target’ов.

Good to know: Systemd — это не только init-система; существуют и другие инструменты экосистемы, например systemd-boot для загрузки. Сравнение загрузчиков — отдельная тема.

Настройка и доработка кастомного сервиса

Systemd позволяет детально настраивать поведение процесса: переменные окружения, UID/GID, ограничения ресурсов, таймеры, зависимости и т. д. Ниже — ключевые изменения и шаблоны.

Добавление переменных окружения

Переменные окружения полезны, когда вы хотите передать конфигурацию в процесс без изменения файлов приложения.

Шаги:

  1. Остановите сервис перед правками:
systemctl --user disable --now my-user-app.service
  1. Откройте unit-файл:
sudo nano ~/.config/systemd/user/my-user-app.service
  1. В секции [Service] добавьте строку Environment:
Environment="EDITOR=/usr/bin/vim" "MY_VAR=production"

Вы можете перечислять несколько переменных в одной строке или использовать файл EnvironmentFile=/path/to/file.

  1. Перезагрузите демон и запустите сервис снова:
systemctl daemon-reload --user
systemctl --user start my-user-app.service

Терминал с примером модифицированного unit-файла и переменной окружения EDITOR.

Совет: при сложной конфигурации удобно использовать EnvironmentFile и хранить его с ограниченными правами доступа.

Запуск system-level сервиса под конкретным пользователем

Если нужно, чтобы системный сервис запускался от имени непривилегированного пользователя (например, отдельно созданного системного аккаунта), укажите User= и при необходимости Group= в секции [Service].

  1. Полностью отключите сервис:
sudo systemctl stop my-system-app.service
sudo systemctl disable my-system-app.service
  1. Убедитесь, что пользователь существует: id username.

Проверка существования пользователя для Systemd unit.

  1. Отредактируйте unit-файл:
sudo nano /etc/systemd/system/my-system-app.service

Добавьте в [Service]:

User=appuser
Group=appgroup
  1. Перезапустите сервис:
sudo systemctl daemon-reload
sudo systemctl start my-system-app.service
  1. Проверьте владельца процесса:
ps -o user= -p $(systemctl show my-system-app.service -p MainPID | awk -F= '{print $2}')

Терминал с информацией о пользователе, от имени которого запущен процесс службы.

Примечание: для сервисов, запущенных как непривилегированный пользователь, убедитесь, что файлы и каталоги имеют соответствующие права доступа.

Ограничение потребления ресурсов сервисом

Systemd поддерживает директивы контроля ресурсоёмкости: MemoryHigh, MemoryMax, CPUQuota, TasksMax и др. Это удобно для контейнеризации и защиты хоста от «пожирания» ресурсов.

Пример: добавить мягкий лимит памяти

  1. Отключите сервис и отредактируйте unit-файл:
sudo nano /etc/systemd/system/my-system-app.service
  1. В секции [Service] добавьте, например:
MemoryHigh=500M
MemoryMax=1G
CPUQuota=50%
TasksMax=512
  1. Перезагрузите daemon и включите сервис:
sudo systemctl daemon-reload
sudo systemctl enable --now my-system-app.service
  1. Мониторинг:
systemd-cgtop

Вывод systemd-cgtop для мониторинга групп контроля ресурсов.

Подсказка: список поддерживаемых ресурсов смотрите через man systemd.resource-control.

Частые ошибки и когда Systemd может не подойти

  • Нельзя заменить полноценный менеджер процессов для контейнеров с очень специфичными требованиями — там чаще используют supervisor, runit или встроенные механизмы оркестраторов.
  • Неправильные пути в ExecStart (относительные вместо абсолютных) — наиболее частая ошибка.
  • Запуск GUI-приложений как system-level сервисов может не работать из-за отсутствия X/Wayland сессии.
  • Ожидание network-online.target вместо network.target может привести к гонкам при старте — выбирайте зависимости осознанно.

Контрпример: если у вас лёгкий однопоточный скрипт, который должен запускаться только при входе в определённую графическую сессию, лучше использовать пользовательские автозагрузки DE (например, autostart .desktop) вместо systemd.

Альтернативные подходы

  • systemd timers — альтернатива cron для планирования задач с интеграцией в Systemd.
  • supervisor, monit — для простого мониторинга процессов с минимальной конфигурацией.
  • Docker/Podman — изоляция и управление lifecycle через контейнеры.
  • systemd-nspawn — лёгкая контейнеризация на базе Systemd.

Каждый инструмент имеет свои плюсы: контейнеры дают изоляцию, supervisor прост для скриптов, а Systemd — глубинную интеграцию с системой и мощные ограничения.

Практическая методология: как внедрять кастомный сервис (шаги)

  1. Прототип: создайте unit-файл в ~/ и протестируйте локально.
  2. Логирование: убедитесь, что приложение пишет в stdout/stderr или файл; Systemd перехватывает stdout/stderr в journal.
  3. Права: проверьте права на бинарник и рабочие каталоги.
  4. User vs System: выберите режим запуска (user/system).
  5. Ограничения: добавьте ресурсные лимиты для прод-окружения.
  6. Мониторинг: настройте журналирование и alert’ы.
  7. Документация: положите unit-файл и инструкцию развёртывания в репозиторий.

Роли и чек-лист для внедрения

Администратор:

  • Проверил абсолютные пути в ExecStart.
  • Настроил User/Group и права на файлы.
  • Добавил Resource limits и проверил их работу.

Разработчик:

  • Обеспечил корректный лог в stdout/stderr или файл.
  • Предусмотрел graceful shutdown (SIGTERM).
  • Тестировал конфигурацию в user-сессии.

Оператор/DevOps:

  • Настроил systemd timers/units для автозапуска и резервного рестарта.
  • Настроил мониторинг и alert’ы по journal и systemd-cgtop.

Критерии приёмки

  • Сервис успешно стартует и остаётся в статусе active (running) после reboot.
  • Основной PID соответствует ожидаемому бинарю.
  • Ограничения ресурсов применяются (проверка через systemctl show и cgroups).
  • Логи видны через journalctl -u или systemctl status.

Пример тестов:

  • unit-файл с некорректным ExecStart должен давать failed и сообщение об ошибке в journal.
  • При достижении MemoryHigh сервис должен получать OOM-уведомления и корректно переходить в restart (если настроено Restart=on-failure).

Безопасность и жёсткая настройка

  • Минимизируйте права: используйте User= и Group=, когда это возможно.
  • Ограничьте доступ к EnvironmentFile и unit-файлам правами 644/640 в зависимости от необходимости.
  • Не храните секреты в unit-файлах. Используйте защищённые файлы или секретные менеджеры.
  • Настройте PrivateTmp=yes, NoNewPrivileges=yes, ProtectSystem=strict для уменьшения поверхности атаки.

Пример добавлений в [Service]:

PrivateTmp=yes
NoNewPrivileges=yes
ProtectSystem=full
ProtectHome=yes

Эти опции изолируют процесс и ограничивают доступ к файловой системе.

Короткий глоссарий

  • Unit — описание ресурса (сервиса, сокета, таргета) для systemd.
  • ExecStart — команда запуска процесса.
  • Target — группа unit’ов, аналог runlevel.
  • cgroup — механизм ядра Linux для ограничения ресурсов.

Заключение

Systemd предоставляет единый и гибкий способ управления процессами в Linux. Создание кастомных unit-файлов даёт контроль над запуском, правами, окружением и потреблением ресурсов. Правильная настройка повышает надёжность и безопасность сервисов.

Короткое резюме:

  • Выберите между system-level и user-level в зависимости от требований привилегий;
  • Всегда используйте абсолютные пути в ExecStart;
  • Ограничения ресурсов и изоляция повышают устойчивость системы;
  • Тестируйте и документируйте unit-файлы перед развертыванием в прод.

Image credit: Mikhail Fesenko via Unsplash. All alterations and screenshots by Ramces Red.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Несколько аккаунтов Skype: Multi Skype Launcher
Программное обеспечение

Несколько аккаунтов Skype: Multi Skype Launcher

Журнал для работы: повысить продуктивность
Productivity

Журнал для работы: повысить продуктивность

Персональные звуки уведомлений на Android
Android.

Персональные звуки уведомлений на Android

Скачивание шоу Hulu для офлайн‑просмотра
Стриминг

Скачивание шоу Hulu для офлайн‑просмотра

Microsoft Start: персонализированная новостная лента
Новости

Microsoft Start: персонализированная новостная лента

Как изменить имя в Epic Games быстро
Гайды

Как изменить имя в Epic Games быстро