Как создать systemd unit для своего скрипта: пошаговое руководство
От простого скрипта до полноценной службы: разбираем структуру unit-файла, типы сервисов и типичные ошибки
Введение
В Linux-системах управление службами уже давно перешло к systemd. Если у вас есть скрипт на Python, Bash или бинарное приложение, которое должно работать в фоне, автоматически запускаться при загрузке и перезапускаться при сбоях, лучший способ — оформить его как systemd-юнит. В этом руководстве мы разберём, как создать unit-файл с нуля, настроить его и управлять службой.
Что такое systemd unit и зачем он нужен
Systemd — это система инициализации и менеджер служб в большинстве современных дистрибутивов Linux. Unit-файл — это конфигурационный файл, описывающий, как управлять вашим приложением: когда запускать, от какого пользователя, с какими зависимостями и что делать при завершении.
Преимущества использования systemd перед простым запуском через nohup или screen:
Автоматический старт при загрузке системы.
Перезапуск при аварийном завершении.
Централизованное логирование через journald.
Управление зависимостями (запуск после сети, базы данных и т.д.).
Ограничение ресурсов и прав доступа.
Требования
Linux-система с systemd (Ubuntu, Debian, CentOS, Fedora, Arch и др.).
Права root или sudo для размещения файлов в системных каталогах.
Скрипт или приложение, готовое к запуску.
Базовые навыки работы с командной строкой.
Шаг 1: Подготовка скрипта
Убедитесь, что ваш скрипт работает корректно при запуске из командной строки. Например, создадим простой скрипт /opt/myapp/hello.sh:
#!/bin/bash
echo "Служба запущена в $(date)"
while true; do
echo "Работаю... $(date)"
sleep 10
doneСделайте его исполняемым:
chmod +x /opt/myapp/hello.shПроверьте запуск вручную. Если скрипт использует относительные пути, лучше заменить их на абсолютные, так как systemd запускает процессы с другим рабочим каталогом.
Шаг 2: Выбор места для unit-файла
Unit-файлы могут располагаться в нескольких каталогах:
/etc/systemd/system/— для пользовательских служб (рекомендуется)./usr/lib/systemd/system/— для пакетов из репозиториев.~/.config/systemd/user/— для пользовательских служб без root.
Мы будем использовать /etc/systemd/system/, так как это стандартное место для администраторских служб.
Шаг 3: Создание unit-файла
Создайте файл, например /etc/systemd/system/hello.service:
[Unit]
Description=My Hello Service
After=network.target
[Service]
Type=simple
ExecStart=/opt/myapp/hello.sh
Restart=on-failure
User=myuser
[Install]
WantedBy=multi-user.targetРазберём секции подробнее.
Шаг 4: Секция [Unit]
Здесь описываются метаданные и зависимости:
Description— человекочитаемое описание службы.After— указывает, после каких юнитов запускать данный. Например,network.targetгарантирует, что сеть уже поднята.Requires— жёсткая зависимость: если указанный юнит не запустится, наш тоже не будет запущен.Wants— мягкая зависимость.
Для большинства служб достаточно After=network.target.
Шаг 5: Секция [Service]
Самая важная часть. Ключевые параметры:
Type— тип службы.simple— если процесс не форкается (обычный скрипт).forking— если процесс уходит в фон.oneshot— для задач, выполняемых один раз.notify— если приложение поддерживает sd_notify.ExecStart— команда запуска. Указывайте полный путь.ExecStop— команда для остановки (опционально).Restart— политика перезапуска:no,on-failure,always,on-abnormal.UserиGroup— от какого пользователя запускать. Никогда не запускайте от root, если не требуется.WorkingDirectory— рабочий каталог.Environment— переменные окружения.StandardOutputиStandardError— куда направлять вывод (по умолчанию в journal).
Пример с переменными окружения:
[Service]
Environment="PORT=8080"
Environment="DEBUG=false"
ExecStart=/usr/bin/python3 /opt/myapp/app.pyШаг 6: Секция [Install]
Определяет, как служба включается в автозагрузку. WantedBy=multi-user.target означает, что служба будет запущена при переходе в многопользовательский режим (обычный запуск системы).
Шаг 7: Перезагрузка конфигурации systemd
После создания или изменения unit-файла выполните:
sudo systemctl daemon-reloadЭто заставит systemd перечитать все unit-файлы.
Шаг 8: Запуск и проверка службы
Запустите службу:
sudo systemctl start hello.serviceПроверьте статус:
sudo systemctl status hello.serviceВы увидите, активна ли служба, её PID и последние строки лога.
Шаг 9: Включение автозапуска
Чтобы служба запускалась при загрузке:
sudo systemctl enable hello.serviceОтключить автозапуск можно командой disable.
Шаг 10: Просмотр логов
Логи службы доступны через journalctl:
journalctl -u hello.serviceДля просмотра в реальном времени добавьте -f. Чтобы увидеть логи только за сегодня: journalctl -u hello.service --since today.
Шаг 11: Остановка и перезапуск
sudo systemctl stop hello.service— остановить.sudo systemctl restart hello.service— перезапустить.sudo systemctl reload hello.service— перечитать конфигурацию (если поддерживается).
Шаг 12: Настройка прав и безопасности
Systemd позволяет ограничить возможности службы. Полезные директивы в секции [Service]:
PrivateTmp=yes— изолирует /tmp.NoNewPrivileges=yes— запрещает повышение привилегий.ProtectSystem=full— монтирует /usr и /boot только для чтения.ProtectHome=yes— скрывает домашние каталоги.ReadWritePaths=/var/lib/myapp— разрешает запись только в указанные каталоги.
Пример:
[Service]
User=myuser
Group=myuser
PrivateTmp=yes
NoNewPrivileges=yes
ProtectSystem=full
ProtectHome=yes
ReadWritePaths=/var/lib/myappШаг 13: Использование таймеров вместо cron
Systemd умеет запускать задачи по расписанию через таймеры. Создайте hello.timer:
[Unit]
Description=Run hello every hour
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.targetИ службу hello.service с Type=oneshot. Затем включите таймер: sudo systemctl enable --now hello.timer.
Типичные ошибки
1. Забыли `daemon-reload` — изменения не применяются. 2. Относительные пути — systemd не находит скрипт. Используйте абсолютные пути. 3. Неверный `Type` — для скриптов, которые не завершаются, нужен simple, а не oneshot. 4. Запуск от root без необходимости — создаёт угрозу безопасности. 5. Отсутствие прав на файл — скрипт должен быть исполняемым. 6. Конфликт портов — если служба уже запущена вручную. 7. Неправильный `Restart` — always может привести к бесконечному циклу при ошибке конфигурации.
FAQ
Вопрос: Можно ли запускать службу от имени текущего пользователя без root? Ответ: Да, используйте systemctl --user и размещайте unit в ~/.config/systemd/user/. Не забудьте включить loginctl enable-linger, чтобы служба работала после выхода из системы.
Вопрос: Как передать переменные окружения из файла? Ответ: Используйте EnvironmentFile=/path/to/env в секции [Service].
Вопрос: Что делать, если служба сразу падает? Ответ: Проверьте логи через journalctl -u имя.service -e. Часто причина в неверном пути или отсутствии прав.
Вопрос: Как ограничить потребление памяти? Ответ: Добавьте MemoryMax=512M в секцию [Service].
Вопрос: Можно ли использовать systemd в Docker-контейнере? Ответ: Да, но требуются специальные настройки и привилегии. Обычно не рекомендуется.
Итог
Создание systemd-юнита — это стандартный способ превратить ваш скрипт в полноценную службу Linux. Следуя шагам, вы настроите автозапуск, логирование и перезапуск при сбоях. Не забывайте про безопасность: запускайте от непривилегированного пользователя и используйте директивы изоляции. Теперь ваш скрипт будет работать надёжно и управляемо.
Читайте также
Комментарии
Комментарии доступны только зарегистрированным пользователям. Войти
- Пока нет комментариев. Будьте первым.



