Создание собственной службы Systemd
Приложение нужно запускать при старте сервера, перезапускать при падении и вести логи. Shell-скрипты в /etc/rc.local не дают ни перезапуска, ни зависимостей. Systemd решает всё это одной декларацией.
Зачем писать свой unit-файл
Вместо скриптов и супервизоров вроде supervisord systemd даёт единый интерфейс управления службами. Он знает о сокетах, зависимостях, ресурсных лимитах и имеет встроенный journald для логов.
Структура unit-файла
Unit-файл — ini-подобный файл в /etc/systemd/system/ или /run/systemd/system/ для runtime. Имя формата имя.service.
Обязательные секции и директивы
| Секция | Ключ | Назначение |
|---|---|---|
[Unit] | Description | Человеческое описание |
[Unit] | After | Порядок запуска относительно других юнитов |
[Service] | Type | Способ демонизации |
[Service] | ExecStart | Команда запуска |
[Install] | WantedBy | Цель, при которой включается |
Type
simple— процесс сам остаётся в foreground, systemd ждёт егоforking— процесс форкается, родитель завершается (классический демон)oneshot— однократный запуск, не держит процессexec— аналог simple, но с ожиданием завершения ExecStartPre
Для современных приложений почти всегда simple.
Пример: простой сервис приложения
Флаг --user создаёт пользовательский сервис, который живёт вместе с сессией пользователя, а не системой.
Python: venv и gunicorn
В ExecStart указывайте интерпретатор из venv, а не системный python — зависимости сервиса не смешаются с пакетами хоста:
Для WSGI-приложения:
Секреты держите в EnvironmentFile (KEY=VALUE), права 600, владелец root:appuser. Если юнит не стартует, journalctl -u myapp обычно показывает traceback, отсутствующий WorkingDirectory или пропавший env-файл.
Полезные директивы для продакшена
Перезапуск
Зависимости
Ограничения
Логирование
Читать логи:
Активация и управление
Проверка синтаксиса без применения:
Типичные ошибки
Missing ExecStart. Unit падает при запуске, в логах Unit entered failed state.
Не указан Type. По умолчанию может быть simple, но если процесс демонизируется сам, нужен forking.
Неправильный путь к скрипту. Проверяйте, что файл существует и имеет бит исполнения.systemd не найдёт ошибку в пути — просто не запустит.
Runtime unit без перезагрузки. Изменили файл, забыли daemon-reload. Systemd работает со старой версией.
WorkingDirectory не существует. Если указана директория, она должна быть.
Restart=always без Exit. Если процесс корректно завершается, always поднимет его снова. Это не всегда ожидаемо при systemctl stop.
Не редактируйте unit-файлы из пакетов напрямую в /usr/lib/systemd/system/. Они перезаписываются при обновлении. Пользуйтесь drop-in файлами в /etc/systemd/system/<name>.service.d/.
Drop-in пример: