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脚本编程入门。