禁用/靜態 systemd 服務單元始終在重新啟動時啟動(systemd 計時器作為 cron 替換)
概括
每次重新啟動時都會執行一個被禁用(“靜態”)並且只應該由計時器觸發的 systemd 服務單元。
背景
這是一個服務單元 (in
/etc/systemd/system/
),之前有一個[Install]
部分並且是systemctl enable
d。該
[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 單元添加必要的要求,以確保服務單元在所有必需的服務都線上(網路、數據庫等)之前不會執行。否則很可能會失敗。