Архив рассылок сообщества снова открыт. Читать письма 2003-2009
Главная/Блог/Администрирование
Администрирование10 мин чтения

systemd без боли: юниты, таймеры и журналы на практике

Разбираемся, как писать свои сервисы и таймеры systemd и уверенно читать журналы.

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

Простейший .service

Юнит службы - это обычный текстовый файл. Пользовательские юниты кладут в /etc/systemd/system/. Вот минимальный сервис, запускающий скрипт:

[Unit]
Description=Моя резервная копия
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh

[Install]
WantedBy=multi-user.target

Секция Unit описывает метаданные и зависимости, Service - что и как запускать, Install - как включать в автозагрузку. После создания файла выполните перечитывание конфигурации и запуск:

systemctl daemon-reload
systemctl start backup.service
systemctl status backup.service

Типы служб

Параметр Type определяет, как systemd понимает, что служба запустилась.

  • simple - процесс не форкается и работает на переднем плане. Значение по умолчанию.
  • oneshot - разовая задача, которая отработала и завершилась. Идеально для скриптов бэкапа.
  • forking - классические демоны, уходящие в фон.
  • notify - служба сама сообщает о готовности.

Самая частая ошибка новичков - оставить simple для форкающегося демона. Тогда systemd считает службу упавшей и может её перезапускать по кругу. Если процесс уходит в фон, ставьте forking.

Таймеры вместо cron

Таймер - это отдельный юнит, который запускает одноимённую службу по расписанию. Для нашего бэкапа создадим backup.timer:

[Unit]
Description=Ежедневный бэкап

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target

Строка OnCalendar задаёт время в понятном формате. Опция Persistent=true важна: если машина была выключена в момент срабатывания, задача выполнится сразу после включения. Включаем таймер:

systemctl enable --now backup.timer
systemctl list-timers

Команда list-timers покажет все таймеры и время их следующего запуска. Преимущество перед cron в том, что запуск и логи попадают в общий журнал, а таймер можно связать с зависимостями других юнитов.

Чтение журнала

journalctl - единая точка доступа к логам. Несколько приёмов, которые нужны каждый день:

journalctl -u backup.service
journalctl -u backup.service -f
journalctl --since "1 hour ago"
journalctl -p err -b

Флаг -u фильтрует по службе, -f следит в реальном времени, --since ограничивает по времени, -p err показывает только ошибки, а -b - записи текущей загрузки. Чтобы журнал не разрастался, ограничьте его размер в /etc/systemd/journald.conf параметром SystemMaxUse.

Типичные ошибки

Большинство проблем с юнитами решаются двумя командами: daemon-reload после правок и status для чтения причины падения.
  • Забыли daemon-reload после изменения файла - systemd работает со старой версией.
  • Указали относительный путь в ExecStart - нужен только абсолютный.
  • Скрипт полагается на переменные окружения, которых нет у systemd - задавайте их через Environment.
  • Неверный Type - приводит к ложным перезапускам.

Полезные привычки

Перед включением службы в автозагрузку всегда проверяйте её через start и status. Для отладки запускайте с journalctl -f в соседнем окне. А команда systemd-analyze verify покажет синтаксические ошибки в юните ещё до запуска. Освоив эти основы, вы перестанете бояться systemd и начнёте использовать его как удобный инструмент, а не как источник боли.

Вернуться в блог