Cron 定时任务
这页适合作为“定时执行任务的速查与选型入口”。定时任务真正容易出问题的地方,往往不是表达式本身,而是时区、幂等性、日志、重试和任务重叠执行没有处理好。
先选执行方式
- 系统级脚本和运维任务:优先 Linux Cron 或 systemd timer
- 服务内轻量定时逻辑:可用应用层调度器
- 云平台边缘任务:用平台自带的 scheduled trigger
- 需要更强可观察性和状态管理:优先选择带日志和失败重试机制的方案
如果任务很关键,不建议只看“能不能定时触发”,还要看失败后谁来发现、谁来补救。
Cron 表达式
┌──────── 分钟 (0-59)
│ ┌────── 小时 (0-23)
│ │ ┌──── 日 (1-31)
│ │ │ ┌── 月 (1-12)
│ │ │ │ ┌ 星期 (0-7, 0和7都是周日)
│ │ │ │ │
* * * * *
常用示例
# 每分钟
* * * * *
# 每 5 分钟
*/5 * * * *
# 每小时整点
0 * * * *
# 每天凌晨 3 点
0 3 * * *
# 每天 9:30
30 9 * * *
# 每周一 8:00
0 8 * * 1
# 每月 1 号 0:00
0 0 1 * *
# 工作日每天 9:00
0 9 * * 1-5
# 每 6 小时
0 */6 * * *
# 每天 8:00 和 20:00
0 8,20 * * *
Linux Cron
# 编辑当前用户的 crontab
crontab -e
# 查看
crontab -l
# 删除所有
crontab -r
# 编辑其他用户的
sudo crontab -u www-data -e
示例
# 每天 3 点备份数据库
0 3 * * * /opt/scripts/backup-db.sh >> /var/log/backup.log 2>&1
# 每小时清理临时文件
0 * * * * find /tmp -mtime +1 -delete
# 每 5 分钟检查服务状态
*/5 * * * * /opt/scripts/health-check.sh
# 每周日 2 点更新系统
0 2 * * 0 apt update && apt upgrade -y >> /var/log/apt-upgrade.log 2>&1
注意事项
- 使用绝对路径
- 重定向输出避免邮件通知
- 环境变量可能与交互式 shell 不同
# 在 crontab 顶部设置环境变量
PATH=/usr/local/bin:/usr/bin:/bin
SHELL=/bin/bash
推荐实践顺序
建议按这个顺序设计定时任务:
- 先把任务本体改成手动执行可成功
- 再加日志输出
- 再加定时表达式
- 再补时区、失败告警和幂等保护
- 最后再考虑批量任务和并发控制
先保证“手动跑得稳”,再交给调度器。
systemd Timer
更现代的替代方案。
# /etc/systemd/system/backup.service
[Unit]
Description=Database Backup
[Service]
Type=oneshot
ExecStart=/opt/scripts/backup-db.sh
# /etc/systemd/system/backup.timer
[Unit]
Description=Daily Database Backup
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
systemctl enable backup.timer
systemctl start backup.timer
systemctl list-timers
Node.js 定时任务
node-cron
pnpm add node-cron
import cron from "node-cron";
// 每 5 分钟
cron.schedule("*/5 * * * *", () => {
console.log("Running task...");
});
// 每天 9:00
cron.schedule(
"0 9 * * *",
() => {
sendDailyReport();
},
{
timezone: "Asia/Shanghai",
},
);
Cloudflare Workers Cron Triggers
// wrangler.toml
// [triggers]
// crons = ["*/5 * * * *"]
export default {
async scheduled(event, env, ctx) {
ctx.waitUntil(doTask());
},
};
在线工具
| 工具 | 说明 |
|---|---|
| crontab.guru | Cron 表达式解释 |
| crontab-generator | 可视化生成 |
常见问题
命令在终端里能跑,Cron 里不执行
高频原因通常是:
- 路径写成了相对路径
- 环境变量不同
- Shell 不同
- 权限不足
任务重复执行,导致数据混乱
这类任务要优先补:
- 幂等设计
- 锁文件 / 分布式锁
- 执行中保护
- 失败重试策略
时间到了却没按预期触发
优先检查:
- 系统时区
- 表达式是否写错
- 服务是否真的启用
- 平台是否有触发频率限制
风险提醒
- 定时任务不要默认无日志运行
- 影响数据和财务的任务必须有幂等保护
- 批量任务先拿小范围数据试跑,再放大规模
延伸阅读
参考链接
- crontab.guru — 在线解释器
- systemd Timer — Arch Wiki
- node-cron — Node.js 定时任务