# Crontab 指令說明

Cron 背景程式（crond）是 Unix 類作業系統上的背景服務，用於執行排程命令。它從 crontab（cron 表）檔案中讀取設定，這些檔案定義了每個命令的執行時間和頻率。

## 語法

crontab 指令管理每個使用者的 crontab 檔案：

```
crontab [-u user] [-l | -r | -e | -i] [file]
```

## 選項

- **`-e`**: 在預設編輯器（$VISUAL 或 $EDITOR）中編輯目前使用者的 crontab。編輯器結束後安裝新的 crontab。
- **`-l`**: 將目前使用者的 crontab 顯示到標準輸出。
- **`-r`**: 完全移除目前使用者的 crontab。
- **`-i`**: 移除前提示確認（與 -r 一起使用）。
- **`-u user`**: 操作指定使用者的 crontab 而不是自己的。需要 root 權限。
- **`file`**: 從給定檔案安裝 crontab。使用 - 表示標準輸入。

## Crontab 檔案格式

crontab 檔案中的每一行要麼是環境變數賦值、註解（以 # 開頭），要麼是以下格式的 cron 排程：

```
┌───────────── 分鐘 (0–59)
│ ┌───────────── 小時 (0–23)
│ │ ┌───────────── 日 (1–31)
│ │ │ ┌───────────── 月 (1–12 或 JAN–DEC)
│ │ │ │ ┌───────────── 星期 (0–6 或 SUN–SAT)
│ │ │ │ │
* * * * *  要執行的命令
```

## 欄位運算子

- *** (asterisk)**: 比對該欄位的每個可能值。
- **, (comma)**: 指定值列表。範例：日欄位中的 1,15 表示 1 號和 15 號。
- **- (hyphen)**: 定義一個包含範圍。範例：小時欄位中的 9-17 表示 9 點到 17 點的每個小時。
- **/ (slash)**: 定義步進。範例：分鐘欄位中的 */10 表示每 10 分鐘。可以與範圍組合：1-30/5。

## 特殊字串

可以使用以下簡寫字串代替五個時間欄位：

| String | Equivalent |
|--------|-----------|
| `@yearly` / `@annually` | `0 0 1 1 *` |
| `@monthly` | `0 0 1 * *` |
| `@weekly` | `0 0 * * 0` |
| `@daily` / `@midnight` | `0 0 * * *` |
| `@hourly` | `0 * * * *` |
| `@reboot` | `Run once at startup` |

## 環境變數

可以在 crontab 檔案頂部設定環境變數。最常見的有：

- **SHELL**: 用於執行命令的 shell（預設：/bin/sh）。
- **PATH**: 命令的搜尋路徑。Cron 的預設 PATH 非常有限（通常是 /usr/bin:/bin），因此務必使用絕對路徑或明確設定 PATH。
- **MAILTO**: 傳送命令輸出的位置。設為 "" 可停止郵件。預設情況下，輸出會寄給 crontab 擁有者。
- **CRON_TZ**: 設定 crontab 的時區（並非所有系統都支援）。若未設定，cron 使用系統時區。

```
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=admin@example.com

*/5 * * * * /home/user/scripts/backup.sh
```

## 系統 crontab 與使用者 crontab

使用者 crontab（用 crontab -e 編輯）有五個時間欄位加上命令。系統 crontab（/etc/crontab）和 /etc/cron.d/ 中的檔案在時間欄位和命令之間多了一個欄位：執行命令的使用者名稱。

系統 crontab 範例：

```
# /etc/crontab
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m  h  dom mon dow user    command
*/15 *  *   *   *   root    /usr/local/bin/system-check.sh
0    2  *   *   *   backup  /usr/local/bin/nightly-backup.sh
```

## 常見問題

### % (percent sign)

百分號（%）在 crontab 中有特殊含義：它被轉換為換行符，第一個 % 之後的所有內容作為標準輸入傳送給命令。要使用字面量 %，需轉義為 \%。

```
# Wrong — the % will be interpreted
0 0 * * * echo "Date: $(date +%Y-%m-%d)"

# Correct — escape the %
0 0 * * * echo "Date: $(date +\%Y-\%m-\%d)"
```

### PATH

Cron 使用最小化的 PATH 執行。依賴 /usr/local/bin 或其他目錄中命令的腳本應使用絕對路徑或在 crontab 頂部設定 PATH。

### Day-of-month + day-of-week

當日期和星期幾都受限（不是 *）時，cron 會在任一欄位比對時執行命令（OR 邏輯），而不是兩者都比對時。例如，0 0 1 * 5 會在每月 1 號午夜以及每個週五執行。

### Timezone

Cron 預設使用系統時區。如果伺服器在 UTC 但您想使用本地時區執行任務，請使用 CRON_TZ（如支援）或手動轉換時間。

### Output and logging

預設情況下，cron 會將所有輸出（stdout 和 stderr）寄給 crontab 擁有者。要靜默任務，重新導向輸出：command > /dev/null 2>&1。要記錄輸出，重新導向到檔案：command >> /var/log/myjob.log 2>&1。

```
# Discard all output
*/5 * * * * /path/to/script.sh > /dev/null 2>&1

# Log output to a file
*/5 * * * * /path/to/script.sh >> /var/log/myscript.log 2>&1
```

## 實用範例

- [`*/5 * * * *`](https://crontab.run/zh-tw/every-5-minutes) — run every 5 minutes
- [`0 0 * * *`](https://crontab.run/zh-tw/daily) — run once a day at midnight
- [`0 9 * * 1-5`](https://crontab.run/zh-tw/every-weekday-at-9am) — run at 9 AM on weekdays
- [`0 0 1 * *`](https://crontab.run/zh-tw/every-month) — run at midnight on the 1st of every month
- [`0 0 * * 0`](https://crontab.run/zh-tw/every-sunday) — run at midnight every Sunday

Canonical: https://crontab.run/zh-tw/command

---

Maintained by Jsmon — https://jsmon.sh
