跳转至

crontab 定时任务

crontab 是 Linux 系统自带的定时任务调度工具,可以按照设定的时间规则自动执行脚本或命令,白话说就是"定闹钟让电脑自动干活"。

核心知识点

概念说明
cron后台守护进程,负责按时执行任务
crontab用户的定时任务配置表
cron 表达式5 个时间字段:分 时 日 月 周
/etc/crontab系统级定时任务配置文件
/etc/cron.d/系统级定时任务目录
/var/spool/cron/用户级定时任务存放目录
anacron适合不24小时开机的机器,会补执行错过的任务

安装配置

# 大多数 Linux 发行版自带 cron,确认是否安装
which crontab  # 查看 crontab 命令是否存在

# Ubuntu/Debian 安装
sudo apt install cron  # 安装 cron 服务

# CentOS/RHEL 安装
sudo yum install cronie  # 安装 cronie 包

# 确认 cron 服务在运行
sudo systemctl status cron    # Ubuntu/Debian
sudo systemctl status crond   # CentOS/RHEL

# 设置开机自启
sudo systemctl enable cron  # 确保重启后 cron 依然运行

基本使用

cron 表达式格式

┌──────────── 分钟 (0-59)
│ ┌────────── 小时 (0-23)
│ │ ┌──────── 日期 (1-31)
│ │ │ ┌────── 月份 (1-12)
│ │ │ │ ┌──── 星期 (0-7,0和7都是周日)
│ │ │ │ │
* * * * * 要执行的命令

# 特殊符号说明:
# *     表示"每一个"(每分钟、每小时...)
# */5   表示"每隔5个"(每5分钟、每5小时...)
# 1,3,5 表示"第1、3、5个"
# 1-5   表示"第1到第5个"

常用示例

# 每分钟执行一次
* * * * * /home/user/script.sh  # 每分钟运行脚本

# 每小时的第 30 分钟执行
30 * * * * /home/user/script.sh  # 每小时的 30 分执行

# 每天凌晨 2 点执行
0 2 * * * /home/user/backup.sh  # 每天凌晨 2:00 备份

# 每周一早上 8 点执行
0 8 * * 1 /home/user/report.sh  # 每周一 8:00 生成报告

# 每月 1 号凌晨执行
0 0 1 * * /home/user/monthly.sh  # 每月 1 号 0:00 执行

# 每 5 分钟执行一次
*/5 * * * * /home/user/check.sh  # 每隔 5 分钟检查一次

# 工作日(周一到周五)每天 9 点到 18 点,每小时执行
0 9-18 * * 1-5 /home/user/work.sh  # 工作时间每小时执行

# 每天 8 点和 20 点执行
0 8,20 * * * /home/user/twice.sh  # 一天执行两次

管理定时任务

# 编辑当前用户的定时任务
crontab -e  # 打开编辑器编辑定时任务列表

# 查看当前用户的定时任务
crontab -l  # 列出所有定时任务

# 删除当前用户的所有定时任务(危险!)
crontab -r  # 删除所有定时任务,慎用

# 编辑指定用户的定时任务(需要 root 权限)
sudo crontab -u username -e  # 编辑某用户的定时任务

# 查看指定用户的定时任务
sudo crontab -u username -l  # 查看某用户的定时任务

高级用法

输出重定向与日志

# 把输出写入日志文件(追加模式)
0 2 * * * /home/user/backup.sh >> /var/log/backup.log 2>&1
# >> 追加输出到日志文件
# 2>&1 把错误输出也写入同一个文件

# 只记录错误,丢弃正常输出
0 2 * * * /home/user/backup.sh > /dev/null 2>> /var/log/backup_error.log
# > /dev/null 丢弃正常输出
# 2>> 追加错误到日志

# 完全不要任何输出(静默执行)
0 2 * * * /home/user/backup.sh > /dev/null 2>&1
# 所有输出都丢弃

环境变量设置

# 在 crontab 文件开头设置环境变量
SHELL=/bin/bash  # 使用 bash 而不是默认的 sh
PATH=/usr/local/bin:/usr/bin:/bin  # 设置 PATH,cron 默认 PATH 很短
MAILTO=admin@example.com  # 任务输出发送到这个邮箱
HOME=/home/user  # 设置 HOME 目录

# conda 环境的定时任务(生信常用)
0 2 * * * source /home/user/miniconda3/etc/profile.d/conda.sh && conda activate bioinfo && python /home/user/pipeline.py
# 必须先 source conda 初始化脚本,再激活环境,再执行命令

使用锁文件防止重复执行

# 使用 flock 防止任务重叠执行
*/5 * * * * flock -n /tmp/myapp.lock /home/user/slow_task.sh
# flock -n 获取锁,如果获取不到(上次还在跑)就直接跳过
# 这样就不会出现两个实例同时运行的情况

# 使用超时机制(最多跑 1 小时)
0 * * * * timeout 3600 /home/user/task.sh
# timeout 3600 表示最多执行 3600 秒(1小时),超时自动杀掉

特殊时间关键字

# 这些关键字可以替代 5 个时间字段
@reboot    /home/user/startup.sh   # 每次开机执行
@hourly    /home/user/hourly.sh    # 每小时(等于 0 * * * *)
@daily     /home/user/daily.sh     # 每天(等于 0 0 * * *)
@weekly    /home/user/weekly.sh    # 每周(等于 0 0 * * 0)
@monthly   /home/user/monthly.sh   # 每月(等于 0 0 1 * *)
@yearly    /home/user/yearly.sh    # 每年(等于 0 0 1 1 *)

系统级定时任务目录

# 系统预置的定时目录,直接把脚本丢进去就行
/etc/cron.hourly/   # 每小时执行里面的脚本
/etc/cron.daily/    # 每天执行里面的脚本
/etc/cron.weekly/   # 每周执行里面的脚本
/etc/cron.monthly/  # 每月执行里面的脚本

# 把脚本放进去(注意:脚本必须有执行权限,且不能有扩展名)
sudo cp backup.sh /etc/cron.daily/backup  # 复制脚本到每日目录
sudo chmod +x /etc/cron.daily/backup  # 加执行权限

常见报错

问题原因解决
定时任务不执行脚本没有执行权限chmod +x script.sh
命令找不到cron 的 PATH 很短,找不到命令在脚本中使用绝对路径,或在 crontab 开头设置 PATH
conda 环境不生效cron 不会加载 .bashrcsource conda.sh,再 conda activate
脚本执行了但结果不对工作目录不是预期的在脚本开头 cd /正确/目录
收到大量邮件任务有输出但没重定向> /dev/null 2>&1 或设置 MAILTO=""
时间到了没执行cron 服务没启动systemctl start cronenable
权限不够用户没权限执行某些操作sudo crontab -e 编辑 root 的定时任务

速查表

# === crontab 管理 ===
crontab -e              # 编辑定时任务
crontab -l              # 查看定时任务
crontab -r              # 删除所有定时任务(慎用)
sudo crontab -u 用户 -l # 查看指定用户的定时任务

# === cron 表达式速记 ===
* * * * *     # 每分钟
*/5 * * * *   # 每 5 分钟
0 * * * *     # 每小时
0 2 * * *     # 每天凌晨 2 点
0 2 * * 1     # 每周一凌晨 2 点
0 0 1 * *     # 每月 1 号
0 0 1 1 *     # 每年 1 月 1 日

# === 特殊关键字 ===
@reboot       # 开机执行
@hourly       # 每小时
@daily        # 每天
@weekly       # 每周
@monthly      # 每月

# === 日志与调试 ===
grep CRON /var/log/syslog           # 查看 cron 执行日志(Ubuntu)
grep cron /var/log/cron             # 查看 cron 日志(CentOS)
systemctl status cron               # 查看 cron 服务状态

# === 输出重定向模板 ===
命令 >> /var/log/xxx.log 2>&1       # 所有输出追加到日志
命令 > /dev/null 2>&1               # 丢弃所有输出