> Crontab定时任务全攻略:备份与自动化

Crontab是什么

Crontab是Linux自带的定时任务工具,可以让你的脚本在指定时间自动运行。备份数据库、清理日志、监控报警——这些重复性工作都应该交给Crontab。

我管理的每台服务器上都跑着好几个定时任务,省心省力。

Crontab语法

时间表达式

1
2
3
4
5
6
7
┌───────────── 分钟 (0-59)
│ ┌───────────── 小时 (0-23)
│ │ ┌───────────── 日 (1-31)
│ │ │ ┌───────────── 月 (1-12)
│ │ │ │ ┌───────────── 星期几 (0-7, 0和7都是周日)
│ │ │ │ │
* * * * * command

常用时间表达式

表达式含义
* * * * *每分钟
0 * * * *每小时整点
0 2 * * *每天凌晨2点
0 2 * * 0每周日凌晨2点
0 2 1 * *每月1号凌晨2点
*/5 * * * *每5分钟
0 9-18 * * 1-5工作日9点到18点整点
0 2,14 * * *每天2点和14点
@reboot系统启动时执行一次
@daily每天一次(等同0 0 * * *
@weekly每周一次
@monthly每月一次

特殊字符

字符含义示例
*任意值* * * * * 每分钟
,列表1,15 * * * * 第1和15分钟
-范围1-5 * * * * 第1到5分钟
/步长*/10 * * * * 每10分钟

基本操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 编辑当前用户的定时任务
$ crontab -e

# 查看当前用户的定时任务
$ crontab -l
0 2 * * * /root/scripts/backup.sh
*/5 * * * * /root/scripts/check_disk.sh

# 编辑指定用户的定时任务
$ sudo crontab -u www-data -e

# 删除所有定时任务(危险!)
$ crontab -r

实战示例

示例1:每日数据库备份

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
# /root/scripts/backup_mysql.sh

DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backup/mysql"
RETENTION_DAYS=7

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

# 执行备份
mysqldump -u root -p'yourpassword' --all-databases | gzip > $BACKUP_DIR/all_db_$DATE.sql.gz

# 检查备份是否成功
if [ $? -eq 0 ]; then
    echo "[$DATE] 备份成功: all_db_$DATE.sql.gz" >> /var/log/backup.log
else
    echo "[$DATE] 备份失败!" >> /var/log/backup.log
fi

# 删除7天前的备份
find $BACKUP_DIR -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete
1
2
3
4
5
$ chmod +x /root/scripts/backup_mysql.sh

# 添加定时任务:每天凌晨3点执行
$ crontab -e
0 3 * * * /root/scripts/backup_mysql.sh

示例2:自动清理日志

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/bin/bash
# /root/scripts/clean_logs.sh

# 清理30天前的Nginx日志
find /var/log/nginx/ -name "*.log" -mtime +30 -delete

# 清理Docker日志(限制大小)
docker system prune -f --filter "until=72h" 2>/dev/null

# 清理系统日志
journalctl --vacuum-time=7d

echo "[$(date)] 日志清理完成" >> /var/log/maintenance.log
1
2
# 每周日凌晨4点执行
0 4 * * 0 /root/scripts/clean_logs.sh

示例3:服务健康检查

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/bin/bash
# /root/scripts/check_service.sh

SERVICES="nginx mysql redis"

for svc in $SERVICES; do
    if ! systemctl is-active --quiet $svc; then
        echo "[$(date)] $svc 服务挂了,正在重启..." >> /var/log/service_check.log
        systemctl restart $svc
        # 这里可以加发邮件/钉钉通知
    fi
done
1
2
# 每5分钟检查一次
*/5 * * * * /root/scripts/check_service.sh

示例4:SSL证书自动续期

1
2
# 每天检查并续期Let's Encrypt证书
0 2 * * * certbot renew --quiet --deploy-hook "systemctl reload nginx"

常见的坑

坑1:环境变量问题

Crontab运行环境和你手动执行不同,很多环境变量不存在:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 错误写法:直接用命令名
* * * * * node /path/to/app.js

# 正确写法:用完整路径
* * * * * /usr/bin/node /path/to/app.js

# 或者在脚本头部加载环境
#!/bin/bash
source /root/.bashrc
# ...后续命令

查找命令的完整路径:

1
2
3
4
$ which node
/usr/bin/node
$ which python3
/usr/bin/python3

坑2:输出没有重定向

Crontab的输出默认发到系统邮件,容易积满磁盘:

1
2
3
4
5
6
7
8
# 错误写法:没有重定向
* * * * * /root/scripts/check.sh

# 正确写法:输出重定向到日志
* * * * * /root/scripts/check.sh >> /var/log/check.log 2>&1

# 如果不需要输出
* * * * * /root/scripts/check.sh > /dev/null 2>&1

坑3:权限问题

1
2
3
4
5
# 脚本必须有执行权限
$ chmod +x /root/scripts/backup.sh

# 如果用其他用户运行,确保该用户有权限访问相关文件
$ sudo crontab -u www-data -e

坑4:百分号问题

在crontab中%有特殊含义(换行符),需要转义:

1
2
3
4
5
6
7
8
# 错误写法
0 3 * * * tar -czf /backup/www-$(date +%Y%m%d).tar.gz /var/www/

# 正确写法:转义百分号
0 3 * * * tar -czf /backup/www-$(date +\%Y\%m\%d).tar.gz /var/www/

# 更好的写法:把命令放到脚本里,crontab只调用脚本
0 3 * * * /root/scripts/backup.sh

查看Crontab日志

1
2
3
4
5
6
7
# Ubuntu
$ grep CRON /var/log/syslog
Jan 23 03:00:01 server CRON[12345]: (root) CMD (/root/scripts/backup.sh)
Jan 23 03:05:01 server CRON[12346]: (root) CMD (/root/scripts/clean_logs.sh)

# CentOS
$ cat /var/log/cron

在线Crontab生成器

如果记不住语法,推荐使用在线工具:

  • crontab.guru —— 输入表达式实时显示含义
1
2
# 用这个命令验证你的表达式
$ echo "0 2 * * *" | crontab -l  # 查看现有任务

我的Crontab模板

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
$ crontab -l
# ===== 备份 =====
# 每天凌晨3点备份数据库
0 3 * * * /root/scripts/backup_mysql.sh >> /var/log/backup.log 2>&1
# 每天凌晨3点30分备份网站文件
30 3 * * * /root/scripts/backup_files.sh >> /var/log/backup.log 2>&1

# ===== 清理 =====
# 每周日凌晨4点清理日志
0 4 * * 0 /root/scripts/clean_logs.sh >> /var/log/maintenance.log 2>&1

# ===== 监控 =====
# 每5分钟检查服务状态
*/5 * * * * /root/scripts/check_service.sh >> /var/log/service_check.log 2>&1

# ===== 证书 =====
# 每天凌晨2点续期SSL证书
0 2 * * * certbot renew --quiet --deploy-hook "systemctl reload nginx"

总结

Crontab是Linux自动化的基础工具。记住两个原则:1)脚本用完整路径;2)输出要重定向。养成写注释的好习惯,三个月后回来看还知道每条任务是干什么的。

更多实用运维脚本可以看10个超实用Shell脚本。Shell脚本编程基础请参考Shell脚本编程入门

Crontab 定时任务 自动化
cd ..