Cron_job

工具型軟體 **cron** 是一款類 Unix 的作業系統下的基於時間的任務管理系統。使用者們可以通過 **cron** 在固定時間、日期、間隔下，執行定期任務（可以是命令和指令碼）。**cron** 常用於運維和管理，但也可用於其他地方，如：定期下載檔案和郵件。**cron** 該詞來源於希臘語 chronos（χρόνος），原意是時間。

通常，**任務時間表**（crontab）檔案儲存的指令被 crond 常駐程式啟動，常駐程式在背景執行，並每一分鐘檢查是否有定期的作業需要執行。這類作業一般稱為 **cron jobs**。

## crond 常駐程式

crond 是一個用於執行周期命令的常駐程式。通過常駐程式（**`/lib/systemd/system/crond.service`** ）形式執行的 cron 程式稱為 crond。 cron 會通過以下路徑尋找 crontabs：

* **`/etc/crontab`**：為系統**任務時間表**（crontab）**。**以前用於跑以日為單位、以周為單位、以月為單位的任務，現在用於跑 anacron。
* **`/etc/cron.d/`**：該目錄包含系統層次的**任務時間表**（crontabs），不同使用者共同使用。
* **`/var/spool/cron/`**：該路徑包含使用者通過 **`crontab`** 命令建立的**任務時間表**（crontables）。

## crontab 命令

**`crontab`** 命令用於維護每個使用者的**任務時間表**（crontab）檔案。

**`crontab`** 命令用於安裝**任務時間表**（crontab）檔案，刪除和列舉 crond 常駐程式已經在使用的**任務時間表**（crontab）。每個使用者都會擁有自己獨自的**任務時間表**（crontab），這些檔案會存放在 **`/var/spool/`** 目錄下，不建議使用者直接修改這些檔案。MLS 模式下的 SELinux，你可以為這些**任務時間表**（crontab）分等級。

## crontab 檔案

crontab 檔案包含 crond 常駐程式所需的一系列作業和指令。

crontab 檔案的每一行均遵守特定的格式，由空格或 tab 分隔為數個領域，每個領域可以放置單一或多個數值。

### 檔案格式

#### 使用者檔案

**`/var/spool/cron/`** 下的**任務時間表**（crontab）檔案是使用者層次的，格式如下：

```
# 文件格式說明
# ┌──分鐘（0 - 59）
# │ ┌──小時（0 - 23）
# │ │ ┌──日（1 - 31）
# │ │ │ ┌─月（1 - 12）
# │ │ │ │ ┌─星期（0 - 6，表示从周日到周六）
# │ │ │ │ │
# *  *  *  *  * 被執行的命令
```

註：

1. 在某些系統裡，星期日也可以為 7
2. 不很直觀的用法：如果日期和星期同時被設定，那麼其中的一個條件被滿足時，指令便會被執行。請參考下例。
3. 前 5 個域稱之**分時日月周**，可方便個人記憶。

從第六個域起，指明要執行的命令。

#### 系統檔案

**`/etc/crontab`** 和 **`/etc/cron.d/`** 目錄下的**任務時間表**（crontabs）檔案是系統層次的，格式如下：

系統層次的**任務時間表**（crontabs）的任務經常會指定一個或以上的使用者進行執行，因此**任務時間表**（crontabs）檔案需要增加「使用者名稱」欄位。

### 表達式

在一個區域裡填寫多個數值的方法：

* 逗號（**`,`**）表示列舉，例如： **`1,3,4,7 * * * * echo hello world`** 表示，在每小時的 1、3、4、7 分時，列印 "hello world"。
* 連詞符（**`-`**）表示範圍，例如：**`1-6 * * * * echo hello world`** ，表示，每小時的 1 到 6 分鐘內，每分鐘都會列印 "hello world"。
* 星號（**`*`**）代表任何可能的值。例如：在「小時域」里的星號等於是「每一個小時」。
* 百分號 (**`%`**) 表示「每 "。例如：**`*%10 * * * * echo hello world`** 表示，每 10 分鐘列印一回 "hello world"。

#### 非標準字元

某些 cron 程式的擴充版本（如：Quartz Java scheduler）也支援斜線（'/'）運算子，用於表示跳過某些給定的數。例如，「\*/3」在小時域中等於「0,3,6,9,12,15,18,21」等被 3 整除的數； 

### 例子

#### AIX 系統管理員的 Crontab 檔案

```
 #=================================================================
 #      SYSTEM ACTIVITY REPORTS
 #  8am-5pm activity reports every 20 mins during weekdays.
 #  activity reports every hour on Saturday and Sunday.
 #  6pm-7am activity reports every hour during weekdays.
 #  summary prepared at 18:05 every weekday.
 #=================================================================
 0,20,40 8-17 * * 1-5 /usr/lib/sa/sa1 1200 3 &
 0 * * * 0,6 /usr/lib/sa/sa1 &
 0 18-7 * * 1-5 /usr/lib/sa/sa1 &
 5 18 * * 1-5 /usr/lib/sa/sa2 -s 8:00 -e 18:01 -i 3600 -ubcwyaqvm &
```

#### 常見錯誤

一個常見的錯誤是，命令列雙引號中使用 % 時，未加反斜線 \，例如：

```
# 錯誤的例子：
1 2 3 4 5 touch ~/error_`date "+%Y%m%d"`.txt
```

在常駐程式發出的電子郵件中會見到錯誤訊息：

```
/bin/sh: unexpected EOF while looking for `'''''''
```

```
# 正確的例子：
1 2 3 4 5 touch ~/right_$(date +\%Y\%m\%d).txt
  

# 使用單引號也可以解决問題：
1 2 3 4 5 touch ~/error_$(date '+%Y%m%d').txt
  

# 使用單引號就不用加反斜線了。這個例子會產生這樣一個文件~/error_\2006\04\03.txt
1 2 3 4 5 touch ~/error_$(date '+\%Y\%m\%d').txt
```

下例是另一個常見錯誤：

```
# Prepare for the daylight savings time shift
59 1 1-7 4 0 /root/shift_my_times.sh
```

初看似要在四月的第一個星期日早晨 1 時 59 分運行 shift\_my\_times.sh，但是這樣設定不對。

特殊地，當星期域（第五個域）被指定為 \* 時，星期域與日域（第三個域）執行「與」操作；而當星期域（第五個域）被指定為 \* 以外的內容時，星期域與日域執行「或」操作。
所以這個程式會在 4 月 1 日至 7 日以及 4 月餘下的每一個星期日執行。

另一個常見錯誤是對分鐘設定的誤用。下例欲一個程式兩個小時運行一次：

```
# adds date to a log file
* 0,2,4,6,8,10,12,14,16,18,20,22 * * * date >> /var/log/date.log
```

而上述設定會使該程式在偶數小時內的每一分鐘執行一次。正確的設定是：

```
# runs the date command every even hour at the top of the hour
0 0,2,4,6,8,10,12,14,16,18,20,22 * * * date >> /var/log/date.log
```

```
# an even better way
0 */2 * * * date >> /var/log/date.log
```

### 不傳送電子郵件

如果輸出結果來自 crontab 里的命令，那麼 cron 常駐程式會用電子郵件將它發給使用者。

* 若想關閉某個命令的輸出結果，可以將輸出結果重新導向至 `/dev/null`。

```
>/dev/null 2>&1
```

* 在常用的 Vixie cron 中，也可以在檔案的開始部分加入命令來關閉所有命令的郵件輸出：

```
MAILTO=""
```

## cron 命令

## 其他話題

* At：在未來某個時間執行一個作業。
* Anacron：runs job on a periodic interval, anachronistically.
* Launchd：Mac OS X／Darwin cron 替代版本。
* Unix 程式列表

## 參考文獻

## 外部連結

### 文件

* Crontab : Scheduling Tasks（頁面存檔備份，存於網際網路檔案館）
* Computer Hope（頁面存檔備份，存於網際網路檔案館） Linux / UNIX 中 crontab 的用法
* Opengroup's crontab specification（頁面存檔備份，存於網際網路檔案館） - UNIX 03 正式文件
* Crontab - Reference and Examples at mkaz.com（頁面存檔備份，存於網際網路檔案館）

### 軟體

* Cron for Windows
* CVSweb for FreeBSD's cron - Paul Vixie 的 1993 Vixie cron 3.0 版本修補了一些錯誤
* fcron（頁面存檔備份，存於網際網路檔案館） - vixiecron /anacron 的增強版本（GPL）