Linux crontab定时任务完全指南:从入门到生产环境实战(2026)

📝 622 字 · ☕ 2 分钟阅读

什么是crontab?为什么每个运维都要掌握它?

在Linux服务器运维中,定时任务是最基础也最频繁的需求之一。备份数据库、清理日志、发送监控告警、更新SSL证书——这些重复性的工作如果全靠人工手动执行,不仅效率低下,还容易遗漏。

crontab(cron table)是Linux系统中最经典的定时任务管理工具。它能让系统在指定的时间自动执行预设的命令或脚本,是运维工程师必备的核心技能。

本教程将从crontab的基本语法开始,逐步深入到生产环境中的实战场景和最佳实践,无论你是刚接触Linux的新手,还是有几年经验的运维老手,都能从中获得实实在在的帮助。

一、crontab基础:安装与常用命令

大多数Linux发行版默认已安装cron。先确认一下你的系统状态:

$ systemctl status cron
● cron.service - Regular background program processing daemon
     Loaded: loaded (/lib/systemd/system/cron.service; enabled; preset: enabled)
     Active: active (running) since Mon 2026-05-25 08:00:01 CST
   Main PID: 1234 (cron)
     Tasks: 1 (limit: 2327)
    Memory: 2.1M
        CPU: 85ms
     CGroup: /system.slice/cron.service
            └── 1234 /usr/sbin/cron -f

如果没安装,一条命令搞定:

$ sudo apt update && sudo apt install cron -y     # Debian/Ubuntu
$ sudo yum install cronie -y                       # CentOS/RHEL

crontab的常用命令只有5个,背下来就行:

$ crontab -e            # 编辑当前用户的定时任务(最常用)
$ crontab -l            # 列出当前用户的定时任务
$ crontab -r            # 删除当前用户的所有定时任务(慎用!)
$ crontab -u username   # 管理指定用户的定时任务(需要root)
$ crontab -i            # 删除前先确认(安全开关)

二、cron表达式:5个星号搞定一切

crontab的语法看起来简单,但写错一个星号就可能让任务不按预期执行。来,记住这个口诀:

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

几个特殊字符帮你写出更灵活的表达式:

  • * — 每(每个分钟/小时/天…)
  • , — 多个值(如 1,15,30 表示第1、15、30分钟)
  • - — 范围(如 9-17 表示9点到17点)
  • / — 步长(如 */5 表示每5分钟)

三、10个最常用的cron表达式示例

直接上实战,以下场景你大概率都会遇到:

# 每分钟执行一次
* * * * * /usr/bin/php /var/www/cron/every_minute.php

# 每5分钟执行一次
*/5 * * * * /usr/bin/python3 /opt/scripts/check_health.py

# 每天凌晨2:30执行(日志清理的经典时间)
30 2 * * * /usr/local/bin/clean_logs.sh

# 每天上午8点和下午6点各执行一次
0 8,18 * * * /opt/scripts/send_report.sh

# 每周一凌晨3:00执行
0 3 * * 1 /usr/local/bin/weekly_backup.sh

# 每月1号凌晨4:00执行
0 4 1 * * /usr/local/bin/monthly_report.sh

# 每季度执行(1、4、7、10月的凌晨5点)
0 5 1 1,4,7,10 * /usr/local/bin/quarterly_cleanup.sh

# 工作日(周一到周五)每2小时执行一次
0 */2 * * 1-5 /opt/scripts/workday_task.sh

# 每半小时执行一次(适合频繁监控脚本)
*/30 * * * * /opt/scripts/monitor_memory.sh

# 每小时的第15分钟执行
15 * * * * /usr/local/bin/hourly_task.sh

四、实战场景1:Nginx日志每日切割与清理

这是运维中最常见的需求之一。Nginx访问日志如果不做切割,单个文件很快就能撑满磁盘。

先写一个日志切割脚本 /usr/local/bin/rotate_nginx_logs.sh

#!/bin/bash
# Nginx日志每日切割脚本
LOG_DIR="/var/log/nginx"
YESTERDAY=$(date -d "yesterday" +"%Y%m%d")

# 切割访问日志
mv $LOG_DIR/access.log $LOG_DIR/access_$YESTERDAY.log
mv $LOG_DIR/error.log $LOG_DIR/error_$YESTERDAY.log

# 向Nginx发送USR1信号,让它重新打开日志文件
kill -USR1 $(cat /var/run/nginx.pid)

# 保留最近30天的日志,删除更早的
find $LOG_DIR -name "*.log" -mtime +30 -delete

echo "[$(date)] Nginx logs rotated, kept last 30 days"
$ chmod +x /usr/local/bin/rotate_nginx_logs.sh

然后添加到crontab:

$ crontab -e
# 加入这一行,每天凌晨0点执行日志切割
0 0 * * * /usr/local/bin/rotate_nginx_logs.sh >> /var/log/rotate_cron.log 2>&1

五、实战场景2:MySQL数据库自动备份

数据是命根子,自动备份必须安排上:

#!/bin/bash
# MySQL每日备份脚本
BACKUP_DIR="/data/backups/mysql"
DB_USER="backup_user"
DB_PASS="your_secure_password"
DB_NAME="wordpress"
DATE=$(date +"%Y%m%d_%H%M")
RETENTION_DAYS=7

# 创建备份目录
mkdir -p $BACKUP_DIR

# 执行备份
mysqldump -u$DB_USER -p$DB_PASS $DB_NAME | gzip > $BACKUP_DIR/${DB_NAME}_$DATE.sql.gz

# 保留最近7天,删除旧备份
find $BACKUP_DIR -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete

echo "[$(date)] Backup completed: ${DB_NAME}_$DATE.sql.gz ($(du -sh $BACKUP_DIR/${DB_NAME}_$DATE.sql.gz | cut -f1))"

然后添加定时任务(每天凌晨3点备份,避开业务高峰期):

0 3 * * * /usr/local/bin/backup_mysql.sh >> /var/log/backup.log 2>&1

六、实战场景3:系统资源监控与告警

磁盘快满了还等用户来报?自动监控才是正解:

#!/bin/bash
# 磁盘使用率监控告警脚本
THRESHOLD=85
EMAIL="admin@example.com"

df -H | grep -vE '^Filesystem|tmpfs|overlay' | awk '{print $5 " " $6}' | while read output;
do
  usage=$(echo $output | awk '{print $1}' | cut -d'%' -f1)
  partition=$(echo $output | awk '{print $2}')
  if [ $usage -ge $THRESHOLD ]; then
    echo "⚠️ 磁盘告警: $partition 使用率已达 $usage%" | \
    mail -s "[CRITICAL] 磁盘空间告警 - $(hostname)" $EMAIL
  fi
done
# 每10分钟检查一次
*/10 * * * * /usr/local/bin/disk_monitor.sh

七、生产环境最佳实践

1. 始终使用绝对路径

cron的环境变量和终端不同,PATH非常有限。命令和脚本路径一律写绝对路径:

# ❌ 错误方式——cron可能找不到python3
*/5 * * * * python3 /opt/scripts/check.py

# ✅ 正确方式——用绝对路径
*/5 * * * * /usr/bin/python3 /opt/scripts/check.py

2. 输出重定向与日志

cron的默认输出会发邮件给用户,大部分服务器没配邮件,你的日志就丢了。一定要重定向:

# 标准输出和错误都记录到日志文件
0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

# 或丢弃所有输出(确定脚本稳定后)
0 2 * * * /usr/local/bin/backup.sh > /dev/null 2>&1

3. 加锁防止重复执行

对于执行时间可能超过间隔的任务(比如大数据量的数据库备份),需要加锁:

#!/bin/bash
# 使用flock确保同一时间只有一个实例在运行
LOCKFILE="/tmp/backup_mysql.lock"

exec 200>$LOCKFILE
flock -n 200 || exit 1

# 这里是实际的任务内容
mysqldump -u$DB_USER -p$DB_PASS $DB_NAME | gzip > /data/backup/db_$(date +%Y%m%d).sql.gz

flock -u 200

4. 设置环境变量

在crontab文件顶部设置环境变量:

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=admin@example.com

0 2 * * * /usr/local/bin/backup.sh

5. 使用crontab.guru验证表达式

写没把握的表达式时,去 crontab.guru 验证一下,把5个星号填进去,它告诉你实际什么时间执行。这个习惯能救你很多次。本神亲测有效。

八、故障排查:cron任务没执行怎么办?

crontab没按预期执行,90%是以下原因:

  • 路径问题 — cron的PATH远比你终端的短。始终用绝对路径。
  • 权限问题 — 脚本没加执行权限(chmod +x
  • 语法错误 — 用 crontab -l 检查实际写入的内容
  • cron服务没运行 — 检查 systemctl status cron
  • 系统时间不对 — 用 date 确认时区,timedatectl set-timezone Asia/Shanghai 修正

排查命令一条龙:

$ grep CRON /var/log/syslog | tail -20     # Ubuntu/Debian 查看cron日志
$ journalctl -u cron --since "1 hour ago"    # systemd 查看cron日志
$ crontab -l                                 # 确认任务已写入
$ ls -la /var/spool/cron/crontabs/           # crontab文件实际位置

九、进阶:anacron——解决服务器关机错过任务的问题

如果你的服务器不是7×24小时运行(比如笔记本或定时开关机的开发机),cron在关机期间的任务会直接跳过。这时候需要 anacron——它会在系统启动后补执行错过的任务。

$ sudo apt install anacron -y

anacron的任务配置在 /etc/anacrontab

# 格式:周期(天) 延迟(分钟) 任务名 命令
1       5       daily_backup    /usr/local/bin/backup.sh
7       10      weekly_clean    /usr/local/bin/weekly_cleanup.sh
30      15      monthly_report  /usr/local/bin/monthly_report.sh

第一列的天数是什么意思?就是”任务至少每N天执行一次”。如果系统关机了3天,开机后5分钟(第二列设置的延迟)就会执行daily_backup。

常见问题(FAQ)

Q: crontab -e 用什么编辑器?怎么改成vim?

默认是nano,想换成vim执行:select-editor (Ubuntu)或 export EDITOR=vim (加到 ~/.bashrc 永久生效)。

Q: crontab 支持秒级定时任务吗?

不支持。cron的最小粒度是分钟。如果需要秒级任务,用 while sleep 10; do ... done 包装成后台服务,或用 systemd timer 实现。

Q: 修改了crontab需要重启服务吗?

不需要。cron会实时监控crontab文件的变化,crontab -e 保存后立即生效。但如果修改了系统的 /etc/crontab,则需要 systemctl restart cron

— 本文发布于2026年5月27日,命令均在Ubuntu 24.04 LTS / Debian 12上验证通过。如有更新,欢迎收藏订阅。

📤 分享这篇文章