当前位置:首页>Linux>crontab 定时任务实战:让 Linux 替你准时干活

crontab 定时任务实战:让 Linux 替你准时干活

  • 2026-10-11 06:26:12
crontab 定时任务实战:让 Linux 替你准时干活
凌晨三点,你被电话吵醒:"备份脚本没跑!数据丢了!"你爬起来一看——crontab 里写的路径是相对路径,脚本在终端里跑得好好的,放到定时任务里就找不到文件。这种事我见过不下十次。

基本语法

crontab 的时间表达式有 5 个星号:

分  时  日  月  周  命令
*   *   *   *   *   /path/to/script.sh

每个星号的含义:

位置含义范围
第1个分钟0-59
第2个小时0-23
第3个日1-31
第4个月1-12
第5个星期0-7(0和7都是周日)

几个常用例子:

# 每天凌晨3点执行
0 3 * * * /opt/backup.sh

# 每小时执行一次
0 * * * * /opt/check.sh

# 每周一早上9点
0 9 * * 1 /opt/report.sh

# 每5分钟执行一次
*/5 * * * * /opt/monitor.sh

# 每天8点和20点
0 8,20 * * * /opt/sync.sh

管理命令

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

# 查看当前用户的定时任务
crontab -l

# 删除所有定时任务(慎用!)
crontab -r

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

坑1:环境变量

crontab 执行时的环境变量和你终端里完全不同。它只有最基础的 PATH:

PATH=/usr/bin:/bin

你终端里能跑的命令,crontab 里可能找不到。解决办法:

# 方法1:命令用绝对路径
0 3 * * * /usr/bin/python3 /opt/scripts/backup.py

# 方法2:在 crontab 开头设置环境变量
PATH=/usr/local/bin:/usr/bin:/bin
SHELL=/bin/bash
0 3 * * * python3 /opt/scripts/backup.py

坑2:相对路径

crontab 的工作目录是用户家目录,不是脚本所在目录。脚本里写了 ./config.ini 或 data/backup.db,在 crontab 里就会报"找不到文件"。

# ❌ 错误:相对路径
0 3 * * * cd /opt/scripts && python3 backup.py

# ✅ 正确:在脚本里用绝对路径,或者先 cd
0 3 * * * cd /opt/scripts && /usr/bin/python3 backup.py

坑3:输出去哪了

crontab 执行的命令,默认把输出发到本地邮件。你没配邮件的话,输出就丢了,出了错你也看不到。

# 方法1:重定向到日志文件
0 3 * * * /opt/backup.sh >> /var/log/backup.log 2>&1

# 方法2:丢弃输出(不推荐,出错看不到)
0 3 * * * /opt/backup.sh > /dev/null 2>&1

# 方法3:只保留错误输出
0 3 * * * /opt/backup.sh >> /var/log/backup-error.log 2>&1

建议每个定时任务都加日志,出了问题能查。

坑4:权限问题

脚本文件没有执行权限,crontab 调不动它:

# 给脚本加执行权限
chmod +x /opt/backup.sh

如果脚本里操作了需要 root 权限的文件(比如写入 /var/log),要么用 root 的 crontab,要么配 sudoers。

坑5:多实例冲突

如果脚本执行时间超过 crontab 的间隔,上一次还没跑完,下一次又启动了,就会同时跑多个实例。数据库备份脚本如果同时跑两个,大概率出问题。

# 用 flock 文件锁防止多实例
0 * * * * flock -n /tmp/backup.lock /opt/backup.sh

-n 参数表示拿不到锁就直接退出,不等待。

实战:备份脚本

一个完整的备份脚本示例:

#!/bin/bash
# /opt/scripts/backup.sh
# 每天凌晨3点备份数据库

# 设置变量
DATE=$(date +%Y%m%d)
BACKUP_DIR="/backup/mysql"
LOG_FILE="/var/log/backup.log"

# 创建目录
mkdir -p $BACKUP_DIR

# 备份数据库
mysqldump -u root -pMyPassword mydb > $BACKUP_DIR/mydb-$DATE.sql 2>&1

# 检查结果
if [ $? -eq 0 ]; then
    echo "[$(date)] Backup success: mydb-$DATE.sql" >> $LOG_FILE
    # 删除7天前的备份
    find $BACKUP_DIR -name "mydb-*.sql" -mtime +7 -delete
else
    echo "[$(date)] Backup FAILED!" >> $LOG_FILE
fi

对应的 crontab:

# 编辑 crontab
crontab -e

# 添加这一行(注意绝对路径 + 日志重定向)
0 3 * * * /bin/bash /opt/scripts/backup.sh >> /var/log/backup.log 2>&1

系统级定时任务

除了用户级的 crontab -e,还有系统级的定时任务文件:

# 系统级 crontab(需要 root)
/etc/crontab

# 按周期分类的目录
/etc/cron.d/       # 自定义定时任务
/etc/cron.hourly/  # 每小时执行的脚本
/etc/cron.daily/   # 每天执行的脚本
/etc/cron.weekly/  # 每周执行的脚本
/etc/cron.monthly/ # 每月执行的脚本

把脚本扔进对应目录就行,不用写 crontab 语法。比如 logrotate 就是放在 /etc/cron.daily/ 里的。

速查表

编辑:    crontab -e
查看:    crontab -l
语法:    分 时 日 月 周 命令
每5分:   */5 * * * *
每天3点: 0 3 * * *
防冲突:  flock -n /tmp/lock script.sh
加日志:  script.sh >> /var/log/xx.log 2>&1
加权限:  chmod +x script.sh
记住:路径用绝对、输出重定向、脚本加权限。这三条做到了,90% 的 crontab 问题都不会碰上。

— ✦ —

— ✦ —

📢 下期预告:lsof 实战——谁动了我的端口和文件

—— 三页札记

👇 关注我,每周分享运维/Linux/开发实战技巧

最新文章

随机文章