Система мониторинга времени активации службы systemd

Вопрос или проблема

Я хотел бы иметь возможность получать от systemd, сколько времени заняло последнее активация сервиса oneshot. Я подумал о следующих вариантах, но они не совсем меня убедили:

  1. Вычислить InactiveEnterTimestamp - InactiveExitTimestamp, например, прочитав их через интерфейс D-Bus на Python. Это имеет недостаток в том, что значение может быть непоследовательным (=отрицательным), пока сервис работает.

  2. Использовать вспомогательные скрипты в ExecStartPre и ExecStartPost, чтобы сохранить временную метку и вычислить прошедшее время, как только сервис завершится.

  3. Использовать обертку-скрипт вокруг исполняемого файла сервиса, которая сохранит прошедшее время где-то на файловой системе, как только основной исполняемый файл завершится.

  4. Использовать вспомогательный скрипт в ExecStartPost, который сохранит значение, вычисленное в пункте #1.

Я предпочел бы #4, если это возможно, а затем #3, если нет. Что бы вы предложили? Есть ли лучший способ сделать это?

Контекст: Я запускаю Tiny Tiny RSS, у которого есть скрипт обновления ленты, который я запускаю через регулярные интервалы с помощью таймера systemd. Я также запускаю Isync таким же образом, чтобы резервировать содержимое моего почтового ящика Gmail. Моя конечная цель — иметь возможность контролировать, сколько времени занимает каждое включение сервиса, и получать уведомления, если это занимает слишком много времени или не запускалось долго.

Редактирование: Мой файл сервиса выглядит так:

[Unit]
Description=Обновление лент Tiny Tiny RSS
After=network.target mysqld.service postgresql.service

[Service]
Type=oneshot
ExecStart=/usr/bin/php /usr/share/webapps/tt-rss/update.php --feeds
User=ttrss
StandardOutput=syslog
StandardError=syslog

А вот и таймер:

[Unit]
Description=Таймер обновления лент Tiny Tiny RSS

[Timer]
OnBootSec=1s
OnUnitInactiveSec=120s
Persistent=true
Unit=tt-rss.service

[Install]
WantedBy=timers.target

Вычислить InactiveEnterTimestamp – InactiveExitTimestamp

Время активации (в секундах) — это результат:

(ActiveEnterTimestampMonotonic - InactiveExitTimestampMonotonic) / 1e6

Смотрите функцию analyze_plot в файле analyze.c для получения деталей.

Но в вашем юните должно быть RemainAfterExit=yes, чтобы получить ActiveEnterTimestampMonotonic.

Вы можете вычислить ExecMainExitTimestampMonotonic - ExecMainStartTimestampMonotonic в ExecStartPost без RemainAfterExit.

например, прочитав их через интерфейс D-Bus на Python.

Вы можете использовать systemctl, чтобы извлечь эти значения:

$ systemctl show -p InactiveExitTimestampMonotonic -p ActiveEnterTimestampMonotonic unit
InactiveExitTimestampMonotonic=44364325621
ActiveEnterTimestampMonotonic=44369331083

Согласно Обещанию стабильности интерфейса:

Стабильные интерфейсы:

...

Командная строка интерфейсы systemctl, loginctl, journalctl.
Мы гарантируем, что скрипты, вызывающие эти команды, будут продолжать
работать с будущими версиями systemd. Обратите внимание, что выходные данные,
генерируемые этими командами, обычно не включены в обещание,
если это не задокументировано в руководстве. Пример: выходные данные
"systemctl status" не стабильны, но выходные данные "systemctl show" стабильны,
поскольку первый предназначен для чтения человеком, а второй -
для чтения компьютером, и это задокументировано в руководстве.

Моя конечная цель — иметь возможность контролировать, сколько времени занимает каждое включение сервиса, и получать уведомления, если это занимает слишком много времени

Вы можете установить TimeoutStartSec и OnFailure:

TimeoutStartSec=

Настраивает время ожидания для запуска. Если служба-демон не
подтверждает завершение запуска в заданное время, служба будет считаться
неудачной и будет остановлена снова.

OnFailure=

Список из одного или нескольких юнитов, которые активируются, когда
этот юнит входит в состояние "неудача".

или не запускался долго

Вы можете извлечь время последнего успешного запуска из журнала:

 journalctl -u ваш-сервис MESSAGE='Started ваш-сервис.service.'

Но вам следует включить постоянное хранение журналов сообщений.

Ответ или решение

Для мониторинга времени активации сервиса oneshot в systemd, вы можете использовать несколько подходов, однако одним из более эффективных способов является использование параметров, связанных с временными метками, а также настройки вашего сервиса.

1. Использование временных меток

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

  • InactiveExitTimestampMonotonic
  • ActiveEnterTimestampMonotonic

Эти значения можно получить с помощью команды:

systemctl show -p InactiveExitTimestampMonotonic -p ActiveEnterTimestampMonotonic имя_сервиса

Тем не менее, чтобы получить доступ к ActiveEnterTimestampMonotonic, ваш единичный файл сервиса должен содержать следующее:

[Service]
RemainAfterExit=yes

Тогда вы можете рассчитать время активации следующим образом:

время_активации = (ActiveEnterTimestampMonotonic - InactiveExitTimestampMonotonic) / 1e6

2. Использование ExecStartPost

Вы можете реализовать логику расчета времени активации непосредственно в вашем ExecStartPost. Это позволяет вам извлечь временные метки, хранящиеся в systemd, и вычислить разницу. Примерный скрипт может выглядеть так:

#!/bin/bash
inactive_exit=$(systemctl show -p InactiveExitTimestampMonotonic имя_сервиса | cut -d= -f2)
active_enter=$(systemctl show -p ActiveEnterTimestampMonotonic имя_сервиса | cut -d= -f2)

activation_time=$((active_enter - inactive_exit))
echo $activation_time > /path/to/activation_time.log

Добавьте этот скрипт в ExecStartPost вашего сервиса:

ExecStartPost=/путь/к/вашему/скрипту.sh

3. Установка таймаутов и уведомлений

Для того чтобы вы могли реагировать на слишком долгую работу сервиса или если он не запускается долгое время, вы можете использовать параметры TimeoutStartSec и OnFailure. Например:

[Service]
TimeoutStartSec=30
OnFailure=your-failure-handler.service

Это позволит вам настроить, что должно произойти, если запуск вашего сервиса превысит заданный тайм-аут.

4. Мониторинг состояния сервиса

Чтобы отслеживать, когда ваш сервис в последний раз выполнялся успешно, вы можете использовать journalctl. Например:

journalctl -u имя_сервиса MESSAGE='Started имя_сервиса.service.'

Не забудьте включить сохранение логов для обеспечения постоянного доступа к журналам.

Заключение

Изложенные методы помогут вам эффективно мониторить время активации ваших oneshot сервисов и обеспечивать их стабильность. Выбор между использованием временных меток и скриптов — это вопрос предпочтений, но подход с ExecStartPost (вариант #4) позволяет более целостно интегрировать логику прямо в конфигурацию сервиса.

Оцените материал
Добавить комментарий

Капча загружается...