
我有兩個服務(一個視頻播放器和一個圖像識別守護程序),我想每天上午 9 點啟動並在下午 23 點結束運行(以及啟動時運行,儘管系統將持續運行)。對於每項服務,我創建了一個-startup.service
和一個-shutdown.service
.這些服務組合在 adaemon-on.target
和 a中daemon-off.target
,然後分別由daemon-on.timer
和觸發daemon-off.timer
。
經過幾次嘗試和測試後,我發現計時器最初按預期觸發目標,但進入「下一個時間」設定為「不適用」的狀態。
僅僅為了讓兩個應用程式使用計時器運行就需要做大量的工作。我確信它缺少一些明顯的東西,並且希望得到任何提示!
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 設定為在上午 9 點觸發 daemon-on.target:
[Unit]
Description=Daemon Startup Schedule
[Timer]
OnCalendar=9:00
Unit=recog-on.target
Persistent=true
[Install]
WantedBy=timers.target
daemon-off.timer 設定為在下午 23 點觸發 daemon-off.target:
[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
在進行了更多搜尋並閱讀了 systemd 手冊頁後,我設法簡化了一些事情,並獲得了我的服務所需的行為。
首先,我在將 [Service] 部分放入我的文件中時犯了錯誤.target
,這是沒有意義的。其次,我發現了一個PartOf=
聲明,它允許我製作一個以視訊播放器和識別服務作為組件的頂級應用程式。最後,透過使用Conflicts=
選項,我可以使用兩個相互衝突的目標來啟動/停止我的應用程式。然後,附加到這些目標的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
而這個循環還在繼續。我仍然懷疑這是否是配置此功能的最佳方式,並且很想聽到其他建議!