Back

Linux Cron 速查表

Linux Cron 速查表

你已经将 Node 应用部署到 Linux 服务器上,需要一个脚本在每天凌晨 3 点运行。你听说过 cron,但语法看起来很晦涩,而且你找到的教程要么过时,要么充满错误。这份 Linux cron 速查表为你提供了正确的、考虑发行版差异的参考,帮助你可靠地调度 cron 任务。

核心要点

  • Cron 使用五字段格式(分钟、小时、日期、月份、星期几),后跟要执行的命令。
  • 当同时指定日期和星期几时,cron 将它们视为 OR(或)关系而非 AND(与)关系——这是导致意外行为的常见原因。
  • Cron 在有限的、依赖发行版的环境中运行,因此始终使用绝对路径并显式设置 PATH 以确保可移植性。
  • 不同的 Linux 发行版使用不同的 cron 实现,功能支持各不相同。

Crontab 语法:五字段格式

每个 cron 任务遵循以下结构:

┌───────────── 分钟 (0-59)
│ ┌─────────── 小时 (0-23)
│ │ ┌───────── 日期 (1-31)
│ │ │ ┌─────── 月份 (1-12)
│ │ │ │ ┌───── 星期几 (0-6, 星期日=0)
│ │ │ │ │
* * * * * command

特殊字符:

  • * — 任意值
  • , — 列表分隔符 (1,3,5)
  • - — 范围 (1-5)
  • / — 步长值 (*/15 表示每 15 个单位)

重要提示:LW#? 这样的字符是 Quartz 调度器语法,不是标准 cron 语法。不要在 Linux crontab 中使用它们。如有疑问,请通过 man 5 crontab 查看系统自带的文档。

常见调度模式

*/5 * * * *     # 每 5 分钟
0 * * * *       # 每小时整点
0 3 * * *       # 每天凌晨 3 点
0 0 * * 0       # 每周日午夜
0 0 1 * *       # 每月第一天

特殊字符串

大多数 cron 实现支持这些快捷方式(在 BusyBox 等精简系统上支持可能有所不同):

字符串等效表达式
@reboot启动时运行一次
@hourly0 * * * *
@daily0 0 * * *
@weekly0 0 * * 0
@monthly0 0 1 * *
@yearly0 0 1 1 *

注意 @reboot 不能保证网络或其他服务可用;对于需要依赖关系的启动任务,systemd timer 通常是更好的选择。

日期 vs 星期几的陷阱

当你同时指定日期和星期几时,cron 将它们视为 OR(或)关系,而非 AND(与)关系:

0 0 15 * 1    # 在 15 号或任何星期一运行

这让很多人措手不及。如果你需要”15 号,但仅当它是星期一时”,请在脚本内部处理该逻辑。

环境处理

Cron 在有限的非交互式环境中运行。这是大多数任务静默失败的原因。

PATH 行为因发行版和版本而异:

  • 某些系统定义了最小的默认 PATH
  • 其他系统(特别是较新的 Ubuntu 版本)可能从服务环境继承 PATH

不要依赖默认值。为了可移植和可预测的行为,请显式设置所需内容。

安全实践:

# 在 crontab 顶部设置变量
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=""

# 始终使用绝对路径
0 3 * * * /usr/bin/node /home/deploy/app/cleanup.js

注意: MAILTO 仅在安装并配置了本地 MTA 时才有效。许多现代服务器没有 MTA。请显式重定向输出,而不是依赖电子邮件。

输出和日志记录

# 记录所有内容
0 3 * * * /path/to/script.sh >> /var/log/myjob.log 2>&1

# 丢弃所有输出
0 3 * * * /path/to/script.sh >/dev/null 2>&1

# 仅记录错误
0 3 * * * /path/to/script.sh >/dev/null 2>> /var/log/myjob-errors.log

基本 Crontab 命令

crontab -e    # 编辑你的 crontab
crontab -l    # 列出当前任务
crontab -r    # 删除所有任务(小心!)

对于系统级任务,使用 /etc/cron.d/ 文件。注意 /etc/cron.daily//etc/cron.hourly/ 等是通过 run-parts 执行的,不会被 cron 自动扫描。有关命名和执行规则,请参阅 man 8 run-parts

Cron 实现各不相同

不同系统运行不同的 cron 守护进程:

  • Debian/Ubuntu: cron (Vixie 系列,发行版打补丁版本)
  • RHEL/Fedora: Cronie
  • Alpine/容器: BusyBox crond

功能支持(特殊字符串、邮件行为、日志记录)可能有所不同。始终根据本地 crontab(5) 手册页进行验证。

Cron vs Systemd Timer

考虑因素CronSystemd Timer
设置复杂度简单更冗长
错过任务处理跳过可配置 (Persistent=true)
依赖关系可以等待服务/挂载
日志记录手动内置 journald

使用 cron 的场景: 你需要在任何地方都能工作的简单、可移植的调度。

使用 systemd timer 的场景: 你需要依赖管理、跨重启的持久化调度,或与现代 Linux 系统更好的集成。systemd 项目关于 timer 单元 的文档是权威参考。

快速调试检查清单

  1. Cron 是否正在运行? systemctl status cronsystemctl status crond (服务名称因发行版而异)
  2. 检查日志: grep CRON /var/log/syslog (Debian/Ubuntu) 或 /var/log/cron (RHEL/Fedora)
  3. 在受限环境中手动测试你的命令
  4. 验证所有命令和文件的绝对路径
  5. 检查脚本的文件权限

结论

Cron 仍然是在 Linux 上调度任务的最简单方法。掌握五字段语法,理解组合日期字段时的 OR 行为,并考虑特定发行版的环境行为。有了这些基础知识,你的调度任务将可靠运行多年。

常见问题

最常见的原因是环境问题。Cron 在有限的非交互式环境中运行,该环境与你的 shell 不同,并且 PATH 行为因发行版而异。始终使用绝对路径,显式设置所需变量,验证 cron 服务正在运行,并检查系统日志中的错误。

使用星期几字段,范围从星期一 (1) 到星期五 (5)。例如,要在每个工作日上午 9 点运行,使用: 0 9 * * 1-5 /path/to/script.sh。请记住,在标准 cron 语法中,星期日是 0,星期六是 6。

用户 crontab 使用 crontab -e 编辑,按用户存储。/etc/cron.d/ 中的系统 crontab 在时间规范后包含一个额外的用户名字段,用于指示哪个用户运行该命令。系统 crontab 更适合服务和共享管理。

在模拟 cron 的最小环境中手动运行你的命令。例如: env -i PATH=/usr/bin:/bin /path/to/script.sh。这有助于发现缺失的依赖项或路径问题,否则会导致静默失败。

Gain control over your UX

See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay