[Nextcloud筆記]解決cron.php「執行時間過久」的問題

之前看了一下Nextcloud的後台,發現它隔一段時間都會報告背景工作(cron.php)有一段時間沒有執行的錯誤。可是不對啊!我明明就已經設定讓它每5分鐘自動執行一次了啊!怎麼會沒有執行?後來經過一系列的排查,終於發現了問題所在並根除。

注意:以下內容不適用於使用Docker架設的Nextcloud站點。但如果你的Nextcloud是放在VPS(支援建立cron排程工作)上,或者是用一台獨立主機作為伺服器並自行安裝LAMP(或LNMP,筆者的環境屬於此類)運作的話,那麼本文的方法就適合。

正常情況應該是這樣子

排查過程

首先排查的部分是使用中的擴充套件。當時我有爬過文,發現有些擴充套件會令cron,php的執行時間被無限拉長(該文說的是Maps這一套劍);但我看了看套件清單,並沒有任何值得懷疑的套件,於是這部分的嫌疑就被排除了。

接著輪到日誌,想說其中可能會記錄到相關的錯誤。結果一開什麼都沒有,看了個寂寞(後來有解決)。

沒辦法,最後就只能去看systemd的service狀態,看看到底是在搞什麼飛機(我的cron.php是設定透過systemd的timer+service組合執行的)。乍看之下好像沒有問題,但在狀態那邊,我發現問題了:
它的狀態是處於執行中,而且為期還不短。正常情況下應該不用多久就能完成了,但它偏偏要在那邊給你拖台錢。
但是直接敲指令執行時又一切正常…WTF?

解決

好,問題找到了,那要怎麼解決?

首先我懷疑是硬碟定時停轉導致的延遲(我有使用hd-idle來讓硬碟停轉),於是我就將hd-idle移除掉。
結果:無效。

接著我猜可能是檔案系統導致這個問題:當時我用的是btrfs檔案系統(純粹是看上它有透明壓縮這一特性),後來再將檔案系統換回一開始的xfs。
結果:無效。

再來是看php是否漏了必要的模組。我最早用Nextcloud時曾使用過APCu快取模組(現用的是redis),尋思著是不是跟它有關係,於是就裝了回去並修改service檔,讓它執行時自動帶入此模組。
結果:問題依舊。

最後,我在想會不會是service檔當中少了什麼必要的參數,導致它執行時出了問題?於是我就看了官方的說明文件:

官方文件的背景工作頁面中,使用systemd執行背景工作的單元設定內容

然後跟我手上的service檔比對了一下,結果並沒有問題,但是問題依舊。

後來我以現有的內容為基礎,再加入了以下內容:

Type=oneshot #定義這個單元是「執行一次」
TimeoutSec=5m #指定最長執行時間與終止時間,超時則視為失敗;這裡設定為5分
Restart=on-failure #執行失敗時自動重試

加完之後存檔退出,最後執行’sudo systemctl daemon-reload’,讓修改的內容生效。
注意!修改過systemd的單元檔之後必須執行上面這條指令,才算修改完成(除非用的是systemctl edit方式)。

修改之後,Nextcloud的cron工作就執行得很愉快,再也沒有跳什麼很久以前執行的錯誤了。搞了半天才發現就是systemd在陰陽怪氣。

最後備案

再經過上面的排查之後,我就在想這會不會其實就是systemd自己的bug所致?因為我一開始用的是cron,直到之後學會用systemd的timer之後才換到systemd去。使用cron的期間從來沒有發生過執行逾時的問題(至少記憶中是這樣),於是我就打算:如果經過上面的修改之後還是有問題,就乾脆改回一開始的cron。
好在改完之後一切都按照劇本走,那這個備案也就暫時不需要了。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料