Logo

新人日誌

首頁關於我部落格

新人日誌

Logo

網站會不定期發佈技術筆記、職場心得相關的內容,歡迎關注本站!

網站
首頁關於我部落格
部落格
分類系列文

© 新人日誌. All rights reserved. 2020-present.

Cron Job 是什麼?從零開始搞懂 Linux 排程機制

最後更新:2026年7月15日基礎概念

你可能在部署腳本、資料庫備份、或是伺服器維護的文件裡看過「cron job」這個詞。

它到底是什麼東西?

為什麼幾乎每台 Linux 主機上都看得到它的身影?

如果你曾經想過「怎麼讓一支腳本每天凌晨自動跑一次」,那你要找的答案很可能就是 cron。

我們先從最基本的問題開始:cron 到底在解決什麼問題?

Cron 是什麼?

先講一下這個名字是怎麼來的,你就不會只把它當成一個沒有意義的代號。

cron 這個字源自希臘文「chronos」,意思是「時間」,因為它的工作本質,就是要在正確的時間點把事情觸發出來。

舉個例子,假設你希望「每天凌晨兩點自動備份資料庫」,重點不是「執行一次備份」這個動作本身,而是「凌晨兩點」這個時間點——動作是固定的,真正的挑戰在於準時觸發,一分鐘都不能提早或延後太多。

問題是,要做到「隨時掌握時間、時間一到就觸發」,這支程式就不能像一般程式那樣執行完就結束,而是得一直留在背景待命。

在 Unix 的世界裡,這種一直在背景默默執行、不需要你手動操作、系統開機就自動啟動的程式,有個專門的稱呼,叫做 daemon。

cron 就是這樣一支 daemon:因為工作跟時間綁在一起,所以才需要隨時待命,也因此用「時間」的希臘文來命名。

知道這個由來之後,它的功能就很直覺了:你告訴 cron「什麼時間點」該做什麼事,它就負責在對的時間點把事情觸發出來。

具體來說,Cron 是 Linux/Unix 系統裡的一個排程服務(scheduler),做法是每分鐘醒來檢查一次「現在有沒有工作要做」。

如果有,它就把對應的指令跑起來;如果沒有,它就繼續睡回去,一分鐘後再檢查一次。

負責這件事的程式正式名稱就是 cron daemon(通常寫作 crond),也就是前面提到的那支背景程式。

而 cron job,指的就是交給 cron daemon 排程執行的那個工作——可能是一支腳本、一個指令,或是一支程式。

這段小結一下:cron 是排程服務本身,cron daemon 是實際跑在背景的程式,cron job 則是你交給它去執行的任務。

三者的關係搞清楚後,接下來的內容會好懂很多。

值得一提的是,cron daemon 這支背景程式並不是寫死在系統核心裡的東西,而是一個獨立的套件(常見的實作叫 cronie 或 vixie-cron),技術上可以移除、也可以重裝。

不過幾乎所有主流的 Linux 發行版(例如 Ubuntu、Debian、CentOS、Fedora)在預設安裝時就會把它裝好,所以你開一台新的 Linux 主機,通常直接就能用 crontab -e,不用額外裝東西。

Crontab:cron 讀取工作清單的地方

cron daemon 每分鐘檢查一次「有沒有工作要做」,但它是怎麼知道要做什麼、什麼時候做的?

答案是它會去讀一份叫做 crontab 的設定檔。

crontab 全名是 cron table,你可以把它想成是一張時刻表:每一行代表一個 cron job,記錄著「這個工作應該在什麼時間點被觸發」以及「觸發時要執行哪個指令」。

crontab 裡的每一行,格式長這樣:

分 時 日 月 星期 要執行的指令

實際範例:

30 2 * * * /home/user/backup.sh

我們一段一段拆開看:

  • 30:分鐘欄位,代表第 30 分
  • 2:小時欄位,代表凌晨 2 點
  • *:日期欄位,* 代表「每一天都符合」
  • *:月份欄位,同樣代表「每個月都符合」
  • *:星期欄位,代表「星期幾都符合」
  • /home/user/backup.sh:真正要執行的指令

合起來的意思就是:每天凌晨 2 點 30 分,執行一次 backup.sh。

* 這個符號的白話理解是「這個欄位不設限,全部都算」。

如果你只想在特定日期或星期執行,就把 * 換成具體數字。

例如 30 2 * * 1 代表「每週一凌晨 2 點 30 分執行」,因為星期欄位的 1 代表星期一(星期天是 0)。

除了具體數字和 *,crontab 語法還支援幾種常用寫法:

0 */2 * * *   → 每 2 小時的整點執行一次(*/2 代表每隔 2 單位)
0 9-18 * * *  → 每天早上 9 點到晚上 6 點,每個整點都執行(9-18 是範圍)
0 0 1,15 * *  → 每個月的 1 號和 15 號執行(逗號代表列舉多個值)

這段小結:crontab 的五個時間欄位分別對應「分、時、日、月、星期」,搭配 *(不設限)、/(間隔)、-(範圍)、,(列舉)這幾種符號,就能組合出幾乎所有你想要的排程規則。

如何新增、查看、刪除 crontab

了解語法之後,下一個問題是:這份 crontab 檔案要怎麼編輯?

每個使用者都有屬於自己的一份 crontab,cron 提供了專用指令來管理它,而不是叫你直接去改某個檔案。

編輯自己的 crontab:

crontab -e

這個指令會用預設的文字編輯器(通常是 vim 或 nano)打開你的 crontab,你可以在裡面新增、修改、刪除任務。

存檔離開後,cron daemon 就會讀到新的排程規則,不需要重啟系統。

查看目前的 crontab 內容:

crontab -l

刪除整份 crontab(清空所有排程):

crontab -r

這裡有個新手常踩的雷,我們用對比的方式來看:

❌ 有問題的寫法:

30 2 * * * backup.sh

這樣寫在大多數情況下會失敗,因為 cron 執行指令時並不是在你熟悉的終端機環境下跑,它不一定知道 backup.sh 這個相對路徑是相對於哪裡。

✅ 改善後的寫法:

30 2 * * * /home/user/scripts/backup.sh

一律使用絕對路徑,明確告訴 cron 這個檔案完整的位置在哪裡,才能確保排程穩定執行,不會因為工作目錄不同而找不到檔案。

常見陷阱:環境變數、時區與 log

搞懂語法和基本操作之後,實際上線時最容易踩坑的,反而是三個看似跟「排程」無關的細節。

陷阱一:環境變數不見了

你在終端機手動執行一支腳本時,通常會繼承你登入帳號的完整環境變數(像是 PATH、NODE_ENV 這些)。

但 cron daemon 啟動 job 時,用的是一份非常精簡的環境變數,通常只有基本的 PATH,不會載入你 .bashrc 或 .zshrc 裡設定的內容。

這就是為什麼一支腳本你手動執行沒問題,放進 cron 卻找不到指令(例如找不到 node 或 python)。

解法有兩種,你可以擇一使用,或是兩種一起用。

解法一:指令裡明確指定完整路徑

先用 which 指令查出這個指令實際裝在哪裡:

which node

假設輸出是 /usr/bin/node,代表這就是 node 這個指令的絕對路徑。

接下來在 crontab 裡,把原本的 node 換成完整路徑:

30 2 * * * /usr/bin/node /home/user/scripts/backup.js

而不是只寫 node backup.js,靠 cron 幫你去猜 node 在哪裡。

解法二:在腳本開頭自己載入需要的環境變數

如果你的腳本裡用到很多指令,一個一個換成絕對路徑會很麻煩,這時候可以改成在腳本最開頭手動補上需要的環境變數,例如:

#!/bin/bash
export PATH=/usr/local/bin:/usr/bin:/bin:$PATH
export NODE_ENV=production

node backup.js

這樣不管 cron 給的 PATH 有多精簡,腳本執行到 node backup.js 這一行時,環境變數已經被你手動補齊了,也能正常找到指令。

陷阱二:時區設定跟你想的不一樣

cron daemon 使用的是系統設定的時區,不是你電腦或瀏覽器所在地的時區。

如果你的伺服器設定的是 UTC,而你希望「台北時間凌晨 2 點」執行,那你在 crontab 裡寫的小時欄位,要換算成 UTC 時間,而不是直接寫台北時間的 2。

台北時間是 UTC+8,也就是台北時間比 UTC 快 8 小時,換算時要把台北時間往回減 8 小時。

我們用一個實際例子算一次:你希望「台北時間凌晨 2 點」執行,往回減 8 小時,就是「UTC 時間前一天的 18 點」。

所以 crontab 應該寫成:

0 18 * * * /home/user/scripts/backup.sh

小時欄位寫 18,而不是你直覺想寫的 2,因為 cron daemon 是照系統的 UTC 時間在比對,不是照台北時間。

可以用以下指令確認系統目前的時區:

timedatectl

執行後如果看到 Time zone: Etc/UTC,就代表系統用的是 UTC,需要自己換算。

如果看到的是 Time zone: Asia/Taipei,代表系統本身就設定成台北時區,這時候直接寫台北時間的小時數就可以了,不用再換算。

如果你不想每次都手動換算,另外一個做法是在 crontab 檔案最上方指定時區,讓後面的排程都用指定的時區來計算:

CRON_TZ=Asia/Taipei
0 2 * * * /home/user/scripts/backup.sh

這樣寫的話,0 2 就會直接照台北時間凌晨 2 點觸發,不用再自己換算成 UTC。

不過要注意,CRON_TZ 這個寫法不是每一種 cron 實作都支援,用之前建議先確認你系統上的 cron 版本有沒有支援這個語法。

陷阱三:看不到執行結果

cron job 是在背景默默執行的,預設情況下,如果指令有任何輸出(不管是正常的 print,還是錯誤訊息),都不會顯示在你的畫面上,你完全不知道它到底跑成功還是失敗。

這段小結一下解法:主動把輸出導向一個 log 檔案,才能事後回頭檢查:

30 2 * * * /home/user/scripts/backup.sh >> /home/user/logs/backup.log 2>&1

要看懂這行指令,得先知道 Linux 裡每個程式執行時都有兩條輸出管道:一條叫標準輸出(stdout,代號是 1),專門輸出正常訊息;另一條叫標準錯誤輸出(stderr,代號是 2),專門輸出錯誤訊息。

平常你在終端機執行指令時,這兩條管道預設都是輸出到畫面上,所以你才看得到印出來的文字和錯誤訊息混在一起。

>> 這個符號,代表把標準輸出(也就是代號 1 的那條管道)附加寫入後面接的檔案,這裡是寫進 /home/user/logs/backup.log。

用 >>(兩個角括號)而不是 >(一個角括號),是因為 > 每次執行都會清空檔案重寫,>> 才會保留舊紀錄、把新的內容加在後面,不然每次執行完前一次的紀錄就會被洗掉。

2>&1 這段稍微繞一點:2 代表標準錯誤輸出,&1 代表「跟標準輸出導去同一個地方」,合起來的意思就是「把標準錯誤輸出也導到標準輸出現在導去的地方」。

因為前面 >> 已經把標準輸出導去 backup.log 了,所以 2>&1 接在後面,效果就是錯誤訊息也一起寫進同一個 log 檔案。

這裡有個順序上的細節要注意:2>&1 一定要寫在 >> backup.log 後面,如果順序寫反了,錯誤訊息會被導到「畫面」而不是「檔案」,因為 2>&1 執行的當下,標準輸出還沒被導向檔案。

這樣不管腳本執行成功或失敗,結果都會留下紀錄,方便你之後追蹤問題。

另外提醒一點,log 檔案會隨著 cron job 一直執行而越長越大,長期下來可能會佔用不少硬碟空間,實務上通常會搭配 logrotate 這類工具,定期把舊的 log 壓縮或刪除,這部分可以之後再深入研究,這裡先知道有這個問題存在就好。

實務應用:什麼時候該用 cron?

Cron 最適合處理「有固定時間規律、不需要即時反應」的重複性工作,常見場景包括:

  • 資料庫備份:每天凌晨自動備份一次,避免手動忘記
  • 清理暫存檔:每週清掉一次過期的 log 或快取檔案
  • 定期發送報表:每個月 1 號自動寄出上個月的營運數據
  • 健康檢查:每 5 分鐘檢查一次服務是否還活著,異常就發通知

但 cron 也有它的侷限。

如果你需要的是「事件觸發」(例如有人上傳檔案就馬上處理),或是需要更精細的重試機制、任務相依關係管理,cron 就不太夠用了,這種情況通常會考慮 message queue 或是更完整的排程系統(例如 Airflow)。

另外要注意的是,如果一台機器上有大量 cron job,而且彼此之間有時間先後的依賴關係,單純用 crontab 排時間會很難維護,這時候也是該考慮更專業工具的訊號。

重點整理

  • Cron 是 Linux/Unix 上的排程服務,cron daemon 是實際運作的背景程式,cron job 是被排程執行的任務
  • cron daemon 是獨立套件,不是系統核心內建,但主流 Linux 發行版預設都會裝好
  • crontab 是 cron 讀取排程規則的設定檔,格式是「分 時 日 月 星期 指令」五個欄位加上要執行的內容
  • * 代表不設限,/ 代表間隔,- 代表範圍,, 代表列舉多個值
  • 用 crontab -e 編輯、crontab -l 查看、crontab -r 刪除自己的排程
  • 指令一律用絕對路徑,避免 cron 找不到檔案
  • cron 執行環境的環境變數很精簡,可以用 which 查出絕對路徑,或在腳本開頭手動補上環境變數
  • cron 用的是系統時區,跟台北時間換算時要注意時差,也可以用 CRON_TZ 直接指定時區
  • 用 >> log 檔案 2>&1 把標準輸出和標準錯誤輸出都導向同一個 log 檔案,順序不能寫反
  • cron 適合固定時間、重複性高的背景工作,不適合需要即時觸發或複雜依賴關係的任務

目前還沒有留言,成為第一個留言的人吧!

發表留言

留言將在審核後顯示。

基礎概念

目錄

  • Cron 是什麼?
  • Crontab:cron 讀取工作清單的地方
  • 如何新增、查看、刪除 crontab
  • 常見陷阱:環境變數、時區與 log
  • 陷阱一:環境變數不見了
  • 陷阱二:時區設定跟你想的不一樣
  • 陷阱三:看不到執行結果
  • 實務應用:什麼時候該用 cron?
  • 重點整理