12k
All articles

Linux Cron 速查表

使用正确的五字段语法调度 Linux cron 任务,涵盖发行版环境配置技巧及 cron 与 systemd timers 的全面对比。

OpenReplay Team
OpenReplay Team
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 任务即使语法正确也不运行?

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

如何在特定时间每个工作日运行 cron 任务?

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

用户 crontab 和系统 crontab 有什么区别?

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

如何在调度之前测试 cron 任务?

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

Open-source session replay

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.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.