Запуск и остановка служб systemd с помощью OnCalendar на определенный период времени, каждый день

Запуск и остановка служб systemd с помощью OnCalendar на определенный период времени, каждый день

У меня есть две службы (видеоплеер и демон распознавания изображений), которые я хочу запускать в 9 утра и заканчивать в 23 вечера каждый день (а также при загрузке, хотя система будет работать непрерывно). Для каждой службы я создал и -startup.service. -shutdown.serviceСлужбы объединены в daemon-on.targetи , daemon-off.targetкоторые затем запускаются daemon-on.timerи daemon-off.timerсоответственно.

После нескольких попыток и тестов я обнаружил, что таймеры изначально запускают цели, как и ожидалось, но переходят в состояние, в котором время NEXT установлено на n/a.

Это ужасно много работы, чтобы запустить два приложения с таймером. Я уверен, что в нем не хватает чего-то очевидного, и буду признателен за любые советы!

mpv-startup.service запускает службу видеоплеера:

[Unit]
Description=MPV Video Player Startup
After=xorg.target
Requires=xorg.target

[Service]
Environment=DISPLAY=:0
ExecStart=/usr/bin/python3 /opt/videoplayer/app.py
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=10

[Install]
Also=daemon-on.timer

recog-startup.service запускает службу распознавания изображений:

[Unit]
Description=Recog Startup Service

[Service]
Type=simple
WorkingDirectory=/opt/recog
ExecStart=/opt/recog/recog run
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=30

[Install]
Also=daemon-on.timer

mpv-shutdown.service останавливает службу видеоплеера как одноразовую команду

[Unit]
Description=MPV Video Player Shutdown

[Service]
Type=oneshot
ExecStart=/bin/systemctl --user stop mpv-startup.service

[Install]
Also=daemon-off.timer

recog-shutdown.service останавливает службу распознавания изображений с помощью одноразовой команды:

[Unit]
Description=Recog Shutdown Service

[Service]
Type=oneshot
ExecStart=/bin/systemctl --user stop recog-startup.service

[Install]
Also=daemon-off.timer

daemon-on.target объединяет две службы запуска, указанные выше, и также включается при запуске с default.target:

[Unit]
Description=Daemon Startup Target
Wants=recog-startup.service mpv-startup.service
After=recog-startup.service mpv-startup.service

[Service]
Type=oneshot

[Install]
WantedBy=default.target
Also=daemon-on.timer

daemon-off.target объединяет две службы выключения, указанные выше:

[Unit]
Description=Daemon Shutdown Target
Wants=recog-shutdown.service mpv-shutdown.service
After=recog-shutdown.service mpv-shutdown.service

[Service]
Type=oneshot

[Install]
Also=daemon-off.timer

daemon-on.timer настроен на срабатывание daemon-on.target в 9 утра:

[Unit]
Description=Daemon Startup Schedule

[Timer]
OnCalendar=9:00
Unit=recog-on.target
Persistent=true

[Install]
WantedBy=timers.target

daemon-off.timer настроен на срабатывание daemon-off.target в 23:00:

[Unit]
Description=Daemon Shutdown Schedule

[Timer]
OnCalendar=23:00
Unit=daemon-off.target
Persistent=true

[Install]
WantedBy=timers.target

После размещения всего этого ~/.config/systemd/user/я включаю их следующим образом:

systemctl --user enable --now daemon-on.target
systemctl --user enable --now daemon-on.timer
systemctl --user enable --now daemon-off.timer

Который будет автоматически запускать демон при каждой загрузке, и здесь я ожидаю, что таймеры запустят/остановят демон в соответствии с OnCalendar=опцией. В этот момент systemctl --user list-timersмне показывается, что мои два таймера сработают в нужное время (обратите внимание, что я установил таймеры с интервалом всего в 3 минуты, чтобы не ждать вечность):

NEXT                         LEFT         LAST                         PASSED    UNIT            ACTIVATES
Wed 2019-06-26 12:12:00 JST  1min 4s left Wed 2019-06-26 11:35:02 JST  35min ago daemon-off.timer daemon-off.target
Wed 2019-06-26 12:15:00 JST  4min 4s left Wed 2019-06-26 11:40:48 JST  30min ago daemon-on.timer  daemon-on.target

Затем срабатывает таймер выключения, и мой демон останавливается, через несколько минут срабатывает таймер включения, и демон запускается, как и предполагалось. Однако, снова посмотрев на таймеры, я вижу, что они были сброшены, а поля NEXT/LEFT установлены на n/a, и больше никогда не запустят демон. В чем здесь проблема?

NEXT LEFT LAST                         PASSED       UNIT            ACTIVATES
n/a  n/a  Wed 2019-06-26 12:12:06 JST  4min 18s ago daemon-off.timer daemon-off.target
n/a  n/a  Wed 2019-06-26 12:15:33 JST  50s ago      daemon-on.timer  daemon-on.target

решение1

После еще некоторых поисков и прочтения страниц man systemd мне удалось немного упростить ситуацию и добиться желаемого поведения моих служб.

Во-первых, у меня были ошибки при размещении разделов [Service] в моих .targetфайлах, что не имело смысла. Во-вторых, я обнаружил оператор, PartOf=который позволил мне создать приложение верхнего уровня с видеоплеером и службами распознавания в качестве компонентов. И, наконец, с помощью Conflicts=option я мог запускать/останавливать свое приложение, используя две цели, которые конфликтуют друг с другом. S, .timerприкрепленные к этим целям, затем будут переключаться между собой, отключая или включая мою цепочку приложений и соответствующие конфликтующие .targets. Результат по-прежнему содержится в 7 файлах, что больше, чем я хотел бы поддерживать, но он работает так, как требуется.

app.service — это приложение верхнего уровня, хотя это и пустышка, она может запускать что-то другое:

[Unit]
Description=App Service

[Service]
Type=oneshot
ExecStart=/bin/true
RemainAfterExit=yes

[Install]
WantedBy=default.target
Also=app-on.timer app-off.timer

app-mpv.service — это компонент видеоплеера приложения, поэтому он также зависит от xorg:

[Unit]
Description=App Video Player Service
PartOf=app.service
After=app.service
Requires=xorg.target
After=xorg.target

[Service]
Environment=DISPLAY=:0
ExecStart=/usr/bin/python3 /opt/videoplayer/app.py
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=10

[Install]
WantedBy=app.service

app-recog.service — это компонент распознавания изображений приложения, который не зависит от видеоплеера:

[Unit]
Description=App Recognition Service
PartOf=app.service
After=app.service

[Service]
WorkingDirectory=/opt/recog
ExecStart=/opt/recog/recog run
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=30

[Install]
WantedBy=app.service

app-on.target — это виртуальная цель, она становится активной, как только срабатывает app-on.timer, и, в свою очередь, включает app.service:

[Unit]
Description=App Startup Target
Conflicts=app-off.target
Wants=app.service
After=app.service
RefuseManualStart=yes

[Install]
Also=app-on.timer

app-off.target — это виртуальная цель, она становится активной, как только срабатывает app-off.timer, и в свою очередь отключает app.service:

[Unit]
Description=App Shutdown Target
Conflicts=app.service app-on.target
RefuseManualStart=yes

[Install]
Also=app-off.timer

app-on.timer просто запускает app-on.target:

[Unit]
Description=App Startup Schedule

[Timer]
OnCalendar=9:00
Unit=app-on.target
Persistent=true

[Install]
WantedBy=timers.target

app-off.timer просто запускает app-off.target:

[Unit]
Description=App Shutdown Schedule

[Timer]
OnCalendar=23:00
Unit=app-off.target
Persistent=true

[Install]
WantedBy=timers.target

Включение всего этого беспорядка с (с помощью)Эта статья):

systemctl --user enable app app-mpv app-recog
systemctl --user enable --now app-on.timer app-off.timer
systemctl --user start app

Приложение начинает работать, и если я проверю таймеры, то оба они активны, и тот, который наступит первым, будет выполнен первым:

NEXT                         LEFT          LAST PASSED UNIT            ACTIVATES
Wed 2019-06-26 14:00:00 JST  1min 25s left n/a  n/a    app-off.timer app-off.target
Wed 2019-06-26 14:01:00 JST  2min 25s left n/a  n/a    app-on.timer  app-on.target

После срабатывания таймера выключения приложение останавливается, но app-off.targetцель включения остается запланированной:

NEXT                         LEFT     LAST                         PASSED  UNIT            ACTIVATES
Wed 2019-06-26 14:01:00 JST  55s left n/a                          n/a     app-on.timer  app-on.target
n/a                          n/a      Wed 2019-06-26 14:00:04 JST  3ms ago app-off.timer app-off.target

При срабатывании таймера включения он запускает приложение и отключает app-on.target, но снова активирует таймер выключения:

NEXT                         LEFT     LAST                         PASSED  UNIT            ACTIVATES
Thu 2019-06-27 14:00:00 JST  23h left Wed 2019-06-26 14:00:04 JST  57s ago app-off.timer app-off.target
n/a                          n/a      Wed 2019-06-26 14:01:01 JST  5ms ago app-on.timer  app-on.target

И цикл продолжается. Я все еще сомневаюсь, что это лучший способ настройки, и хотел бы услышать другие предложения!

Связанный контент