Три скрытых героя systemd

А вот и сами герои: timer, path и socket

Это невидимые юниты systemd, которые могут заменить cron, inotifyи даже xinetd.

1. Timer

Про timer ты наверняка слышал. Это альтернатива crontab. Позволяет запускать сервис по расписанию. Вместо того чтобы писать крон-джобы, ты создаёшь .service и .timer.

Пример:

/etc/systemd/system/backup.service

[Unit]
Description=Backup job

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/backup.sh
/etc/systemd/system/backup.timer

[Unit]
Description=Run backup daily

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

Активируем:

sudo systemctl enable --now backup.timer
Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
Persistent=true гарантирует запуск пропущенной задачи, если система была выключена.

Всё! Никаких тебе легаси кронтабов, все работает на юнитах, запускается бэкапилка, тикает таймер.

2. Path

Работает как inotifywait или File Watcher: следит за файлами/папками и запускает сервис при изменении.

Пример:

/etc/systemd/system/upload.path

[Unit]
Description=Watch upload folder

[Path]
PathModified=/var/www/bashdays/upload
Unit=process-upload.service

[Install]
WantedBy=multi-user.target
/etc/systemd/system/process-upload.service

[Unit]
Description=Process uploaded files

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/process-upload.sh

Теперь каждый раз когда в папке /var/www/bashdays/upload что-то меняется, автоматически запускается скрипт process-upload.sh.

3. Socket

Заменяет ручной systemctl start, активируя сервис при первом подключении к сокету. Аналог inetd/xinetd Нихуя не понятно, но на примере сейчас всё прояснится.

Пример:

/etc/systemd/system/echo.socket

[Unit]
Description=Echo socket

[Socket]
ListenStream=12345
Accept=yes

[Install]
WantedBy=sockets.target
/etc/systemd/system/echo@.service

[Unit]
Description=Echo service

[Service]
ExecStart=/usr/bin/nc -l -p 12345 -e /bin/cat
StandardInput=socket

В примере, сервис НЕ работает постоянно, он стартует, только когда кто-то подключается к порту 12345.

Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
Когда ты используешь .socket с Accept=yes, systemd открывает сокет сам и ждёт подключения. А когда подключение приходит — создаёт новый экземпляр сервиса, подставляя туда данные об этом соединении. После завершения — сервис умирает. Всё очень экономно и прозрачно.

Как понять, какой экземпляр стартует?

systemd запускает echo@<ID>.service, где <ID> — уникальный идентификатор подключения (например, PID или номер сокета).

journalctl -u echo@*

Зачем нужны скрытые юниты?

  1. Не нужен cron, всё централизовано в systemd.
  2. Не нужен inotify-tools.
  3. Сервисы не висят без дела, запускаются только когда нужно
  4. Журналирование через journalctl

Вот такие пироги. В повседневной работе я применяю timer и path, с сокетами как-то сильно не приходилось париться.

Ну а ты попробуй хотя бы перетащить свои кронджобы в timer и порадоваться бест-практикам.