Systemd-Timer

禁用/靜態 systemd 服務單元始終在重新啟動時啟動(systemd 計時器作為 cron 替換)

  • January 9, 2022

概括

每次重新啟動時都會執行一個被禁用(“靜態”)並且只應該由計時器觸發的 systemd 服務單元。

背景

這是一個服務單元 (in /etc/systemd/system/),之前有一個[Install]部分並且是systemctl enabled。

[Install]部分已刪除,服務已禁用。該服務現在由計時器觸發。計時器設置為每月執行一次並且是持久的,因此它會跟踪上次執行並且不會在重新啟動時觸發,除非在關機時錯過了執行。

systemctl --system daemon-reload我在做出改變後跑了。

計時器工作正常,並按預期觸發服務。

問題

重新啟動時,服務單元始終執行,而不管計時器的最後一次執行以及計時器是持久的事實。我已經(通過systemctl list-timers)驗證了觸發服務單元的不是定時器單元(除非list-timers關於上次觸發時間的輸出是錯誤的)。

systemctl is-enabled <service-unit>顯示static(又名禁用,[Install]單元中沒有部分)。

find /etc/systemd/system/*.wants -name <service-unit>不顯示之前安裝/啟用此服務時剩餘的任何已安裝符號連結。

我懷疑以前安裝此服務單元時存在“遺留”的東西,導致該服務在重新啟動時啟動,但不知道在哪裡查找。

這是在 ubuntu 20.04 上(以防發生已知的錯誤/問題)。

有沒有辦法調試 systemd 為什麼啟動一個單元?(例如,單元 X 開始是因為想要文件 Z 中的 Y)。

有沒有辦法仔細檢查這個服務真的不是由計時器啟動的(而不是僅僅通過list-timers輸出)?

服務單位

# cat /etc/systemd/system/mysql_tzinfo.service
[Unit]
Description=mysql_tzinfo
Wants=mysql_tzinfo.timer

[Service]
Type=oneshot
Environment=
WorkingDirectory=/tmp
ExecStart=/bin/sh -c "/usr/bin/mysql_tzinfo_to_sql /usr/share/zoneinfo | /usr/bin/mysql --user=root mysql"

User=root
Group=root

定時器單元

# cat /etc/systemd/system/mysql_tzinfo.timer
[Unit]
Description=Timer for mysql_tzinfo.service
Requires=mysql_tzinfo.service

[Timer]
Unit=mysql_tzinfo.service
OnCalendar=*-*-05 04:00:00
AccuracySec=30s
Persistent=true

[Install]
WantedBy=timers.target

好的,在寫這篇文章的過程中,我注意到我Requires=mysql_tzinfo.service[Unit]計時器單元部分中有一個。

我突然想到,啟動時計時器的啟動(systemd 的依賴解析)可能會因此而啟動服務Requires。果然,從計時器中刪除這條線並重新啟動….服務不再啟動。這就是我在關注“技術部落格”時沒有仔細檢查每個配置選項的結果。

對於嘗試從 cron 遷移到 systemd 計時器的人的要點總結:

  • 不要在您的服務單元中添加[Install]部分,也不要在您的服務單元中添加部分systemctl enable
  • 不要將 a 添加Requires=<SERVICE_NAME>.service到您的 TIMER 單元。
  • 如果您希望計時器記住它何時執行並在啟動時執行錯過的執行,請添加Persistent=true到您的 TIMER。
  • 計時器在啟動時執行得相當早,因此您應該 After=向 SERVICE 單元添加必要的要求,以確保服務單元在所有必需的服務都線上(網路、數據庫等)之前不會執行。否則很可能會失敗。

引用自:https://unix.stackexchange.com/questions/685573