Linux crontab 完整指南

7 阅读4分钟

Linux crontab 完整指南:从入门到生产实践

crontab 是 Linux/Unix 系统内置的定时任务工具,无需安装任何依赖,是后端开发和运维人员的必备技能。本文覆盖 crontab 的全部用法、常见坑和生产最佳实践。


一、crontab 基础命令

# 编辑当前用户的 crontab
crontab -e

# 查看当前用户的 crontab 列表
crontab -l

# 删除当前用户的所有 crontab(危险!)
crontab -r

# 编辑指定用户的 crontab(需要 root)
crontab -u username -e

# 查看指定用户的 crontab
crontab -u username -l

二、Cron 表达式语法

┌───────────── 分钟 (0-59)
│ ┌───────────── 小时 (0-23)
│ │ ┌───────────── 日 (1-31)
│ │ │ ┌───────────── 月 (1-12)
│ │ │ │ ┌───────────── 星期 (0-707都是周日)
│ │ │ │ │
* * * * * /path/to/command

特殊符号说明:

符号含义示例
*任意值* * * * * 每分钟
,枚举1,15 * * * * 每小时1分和15分
-范围1-5 * * * * 每小时1到5分
*/n步长*/5 * * * * 每5分钟

常用表达式速查:

表达式含义
0 9 * * 1-5工作日每天早上9点
0 */2 * * *每2小时
0 0 * * *每天凌晨0点
0 0 * * 0每周日凌晨0点
0 0 1 * *每月1号凌晨0点
*/5 * * * *每5分钟
0 9,18 * * 1-5工作日早9点和晚6点

💡 不想手写表达式?用 Hey Cron 直接输入"每天早上9点"生成,同时支持导出 Kubernetes、GitHub Actions 等多平台格式。


三、crontab 文件格式

除了 crontab -e 编辑,也可以直接写文件。系统级 crontab 在 /etc/crontab,格式多一个用户字段:

# /etc/crontab 格式(多一个 username 字段)
0 9 * * 1-5 root /usr/local/bin/backup.sh

# 用户级 crontab 格式(无 username 字段)
0 9 * * 1-5 /usr/local/bin/backup.sh

也可以在 /etc/cron.d/ 目录下新建文件(系统级,推荐用于服务):

# /etc/cron.d/myapp
0 9 * * 1-5 www-data /usr/local/bin/myapp-task.sh

四、环境变量问题(最常踩的坑)

crontab 的执行环境和你的终端环境完全不同,默认只有极少的环境变量。

坑 1:PATH 不包含常用目录

# ❌ 这样会失败,因为 cron 的 PATH 里没有 /usr/local/bin
0 9 * * * node /app/script.js

# ✅ 用绝对路径
0 9 * * * /usr/local/bin/node /app/script.js

查看你的命令绝对路径:

which node    # /usr/local/bin/node
which python3 # /usr/bin/python3
which npm     # /usr/local/bin/npm

坑 2:在 crontab 顶部定义环境变量

# crontab 文件顶部定义环境变量
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SHELL=/bin/bash
HOME=/home/youruser

# 任务
0 9 * * * node /app/script.js

坑 3:加载 .bashrc / .profile

# 显式加载用户环境
0 9 * * * bash -l -c '/usr/local/bin/node /app/script.js'

五、日志和调试

查看 cron 执行日志

# Ubuntu/Debian
grep CRON /var/log/syslog

# CentOS/RHEL
grep CRON /var/log/cron

# 实时查看
tail -f /var/log/syslog | grep CRON

把任务输出重定向到日志文件

# 把标准输出和错误输出都写入日志
0 9 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

# 只记录错误
0 9 * * * /usr/local/bin/backup.sh >> /dev/null 2>> /var/log/backup-error.log

# 忽略所有输出(静默模式)
0 9 * * * /usr/local/bin/backup.sh > /dev/null 2>&1

带时间戳的日志

0 9 * * * echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting backup" >> /var/log/backup.log && /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

六、生产最佳实践

1. 用脚本文件,不要把命令直接写在 crontab 里

# ❌ 不推荐,难以维护
0 9 * * * cd /app && node index.js --task=backup && echo "done"

# ✅ 推荐,用脚本文件
0 9 * * * /app/scripts/backup.sh

脚本文件头部加上:

#!/bin/bash
set -euo pipefail   # 遇到错误立即退出

# 切换到项目目录
cd /app || exit 1

2. 防止任务重叠运行(flock)

# 使用 flock 加锁,防止上一个任务还没跑完下一个就启动
0 * * * * flock -n /tmp/mytask.lock /app/scripts/task.sh

3. 任务超时保护

# 最多运行 300 秒,超时强制终止
0 9 * * * timeout 300 /app/scripts/backup.sh

4. 执行失败发送告警

#!/bin/bash
# backup.sh
set -e

do_backup() {
    # 实际备份逻辑
    rsync -avz /data/ user@backup-server:/backup/
}

if ! do_backup; then
    # 失败时发送邮件(需要配置 mail)
    echo "Backup failed at $(date)" | mail -s "ALERT: Backup Failed" admin@example.com
    exit 1
fi

echo "Backup completed at $(date)"

5. 使用 run-parts 管理多个任务

# 每小时运行 /etc/cron.hourly/ 目录下的所有脚本
0 * * * * run-parts /etc/cron.hourly

# 系统默认已经有这几个目录
/etc/cron.hourly/
/etc/cron.daily/
/etc/cron.weekly/
/etc/cron.monthly/

七、常见问题排查

问题 1:任务列表里有,但没有执行

检查步骤:

# 1. 确认 cron 服务在运行
systemctl status cron        # Ubuntu
systemctl status crond       # CentOS

# 2. 查看日志
grep CRON /var/log/syslog | tail -20

# 3. 手动执行脚本确认没有错误
bash /app/scripts/task.sh

问题 2:权限不足

# 确保脚本有执行权限
chmod +x /app/scripts/task.sh

# 确认运行 cron 的用户有权限访问相关文件
ls -la /app/scripts/task.sh

问题 3:时区问题

Linux crontab 使用系统时区:

# 查看系统时区
timedatectl

# 设置系统时区
timedatectl set-timezone Asia/Shanghai

# 或者在 crontab 文件顶部指定时区
CRON_TZ=Asia/Shanghai
0 9 * * * /app/scripts/task.sh

总结

场景方案
防止重叠flock -n /tmp/task.lock
任务超时timeout 300
环境变量crontab 顶部定义 PATH
日志记录>> /var/log/task.log 2>&1
时区CRON_TZ=Asia/Shanghai

crontab 简单可靠,适合单机定时任务。如果需要分布式、有界面管理、任务依赖等功能,可以考虑升级到 Airflow 或 Kubernetes CronJob。


定时任务的 Cron 表达式和其他平台格式互转,可以用 Hey Cron,输入自然语言一键生成多平台配置。