我們設定的守護程序重新啟動了我們刻意停止的服務
維運
我們其中一個守護程序會啟動任何已啟用但未執行的服務。十月份有兩次,它啟動了我們刻意停止的服務。第二次,我們其中一個網站的訪客大約有 45 分鐘收到錯誤訊息。
為什麼需要這個守護程序
如果一個服務收到 SIGTERM 後正常退出,例如因為有人用名稱強制終止它,在 systemd 眼中它並不算「失敗」。Restart=on-failure 不會將它重新啟動,systemctl --failed 也不會列出它。它會保持停止狀態,直到有人剛好注意到為止。因此,守護程序會尋找已啟用但未執行的服務,並將其啟動。
問題在於,您手動停止的服務看起來完全一樣。
第一次
10 月 7 日,我們於 12:47 使用 systemctl stop 停止了一個影片處理程序,以便編輯其工作佇列。12:55 時它又開始運行了:守護程序已將其啟動。
第二次
10 月 21 日,我們需要那台同時為我們兩個網站提供服務的機器的記憶體來進行模型測試。一個腳本停止了網站的網頁應用程式、一個同步作業和一個資料庫容器,同樣是使用 systemctl stop。大約五分鐘後,一個監控網站的排程器,以及 19:14 的守護程序,將通道和網頁應用程式重新啟動。
通道重新開始接收流量,但網頁應用程式無法回應:測試中的模型佔用了機器 114 GiB 的記憶體。從大約 19:14 到 20:00,部分訪客收到 502 錯誤。20:00 時,我們停用了通道、網頁應用程式和同步作業,並停止了監控排程器。
我們現在使用的規則
- 透過停用服務來暫停它:
sudo systemctl disable --now <unit>。使用sudo systemctl enable --now <unit>將其恢復。我們的守護程序只檢查已啟用的服務,因此停用的服務不會被干擾。 - 暫停所有可能將其重新啟動的項目:前方的通道以及任何監控它的排程器。
- 短暫停止是一場競賽。如果您只使用
stop,請在下一次檢查之前完成,在我們的機器上,這通常發生在幾分鐘之內。
同月份遇到的另外兩個 systemd 陷阱
systemctl mask --runtime對/etc/systemd/system中的單元檔案毫無作用。/etc中的單元優先於/run中的執行時遮蔽,因此指令會成功執行,但服務仍會啟動。若要暫停服務,我們使用帶有ConditionPathExists=!/etc/<name>.hold的 drop-in:只要該檔案存在,服務就不會啟動,無論是在開機時還是手動啟動。systemctl is-active會將正在執行的 oneshot 服務視為非活動狀態。 當Type=oneshot服務執行時,其狀態為「activating」,因此is-active會輸出該狀態並回傳 3。像while systemctl is-active --quiet job.service; do sleep 60; done這樣用於等待夜間工作的迴圈會立即退出。請改為讀取狀態:active、activating、reloading 或 deactivating 都表示服務仍在執行中。
Factory Floor 會監控已啟用但未執行的服務。預設情況下,它僅報告這些服務,只有當您開啟該選項時才會啟動它們。自 1.0.3 版起,其警示訊息也會說明如何刻意暫停服務,其操作手冊也有相同說明。