# 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-cn/every-5-minutes) — run every 5 minutes
- [`0 0 * * *`](https://crontab.run/zh-cn/daily) — run once a day at midnight
- [`0 9 * * 1-5`](https://crontab.run/zh-cn/every-weekday-at-9am) — run at 9 AM on weekdays
- [`0 0 1 * *`](https://crontab.run/zh-cn/every-month) — run at midnight on the 1st of every month
- [`0 0 * * 0`](https://crontab.run/zh-cn/every-sunday) — run at midnight every Sunday

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

---

Maintained by Jsmon — https://jsmon.sh
