
У меня есть две службы (видеоплеер и демон распознавания изображений), которые я хочу запускать в 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
И цикл продолжается. Я все еще сомневаюсь, что это лучший способ настройки, и хотел бы услышать другие предложения!