Cron job not work

筆記在伺服器上執行 cronjob 會碰到的一些問題以及解決方法

Cron job not work
Photo by Andrea De Santis / Unsplash

最近剛好有個機會寫了一個簡單的 Nodejs 爬蟲,串上 LINE Notify 功能每天定時幫我抓一些東西,透過 LINE 傳送結果給我,當然不可能每次要爬的時候就在本地敲 node index.js 這樣重複的事情當然是交給電腦來做啊!所以我就決定把程式丟上自己的 VPS 交給他來幫我做了。

問題

在伺服器上設定好環境之後,手動跑了一下

node index.js

確認運行正常,接著就放上 crontab 幫我們定期觸發,執行 crontab -e 編輯 crontab
當我在測試時我會下

*/1 * * * * node /path/to/app/index.js

好像沒有觸發任何事情?這個時候就必須要花點時間來查找到底為什麼了

解決方法

於是我們加上 log(前提是你的 js 程式碼有輸出 console.log)

*/1 * * * * node /path/to/app/index.js >> /path/to/app/cron.log

要是沒有 log 檔案出現,可以看一下系統的 log 確認 cronjob 在執行的時候發生什麼事情
像我的系統版本為 ubuntu 16.04 我會查看

sudo tail -f /var/log/syslog

確認是否有執行的 log 例如:

Sep 11 02:25:01 ubuntu CRON[30108]: xxxxxxxxx

通常我會把 path 都給寫成絕對路徑,避免出現非預期的問題,例如

*/1 * * * * cd /home/jimmy8646/tsn-crawler && $(which node) index.js >> /home/jimmy8646/tsn-crawler/cron.log

我直接使用 $(which node) 來獲得 node 的絕對路徑,這個在使用 nvm 管理套件上很好用,直接獲取當下版本的 node 路徑
如果你的錯誤訊息是 (CRON) info (No MTA installed, discarding output) 你可以選擇兩種方法

  • 安裝 MTA 套件,將 cronjob 結果寄送給自己
  • 直接忽略這個錯誤

編輯 crontab 在最上方寫入環境變數

MAILTO=""

這樣這個錯誤訊息就會消失不見。

此時可能會碰上另一個問題,例如 cronjob 有執行了,可是好像還是有點不太通的感覺

Sep 10 12:00:01 ubuntu CRON[26466]: (jimmy8646) CMD (xxxxxxxxxxx)

如果搜尋一下大概能發現,crontab 內的環境變數跟你現在終端機的環境變數是不同的,所以可能導致程式在執行上會因為環境變數不同導致執行結果失敗。詳細原因可以看鳥哥或是這篇 cron 如何忽略系統的環境變數

我自己是選擇比較偷懶的方式,就是直接把我的 path 貼到 crontab 內,先在終端機內打上

echo PATH=$PATH

你就會得到 PATH=XXXXXXXXX 然後直接貼到 crontab 上方
CleanShot-2023-09-11-at-02.44.06@2x

應該就可以順利執行了。