Linux Crontab定时任务完全指南:语法详解、常用场景与执行异常排查

Crontab是Linux服务器自动化的基石工具,从每天凌晨备份数据库、定时清理日志,到每小时同步文件、每分钟检查服务状态,几乎所有周期性任务都依赖cron来完成。本文从语法到实战,给出完整指南。

一、Cron表达式语法

# crontab格式:
# 分钟  小时  日期  月份  星期  命令
#  *     *     *     *     *   /path/to/command
#  0~59  0~23  1~31  1~12  0~7(0和7均为周日)

# 特殊符号:
# *  代表所有可能的值(每分钟/每小时/每天)
# ,  列举多个值(1,3,5 = 1日、3日、5日)
# -  范围(1-5 = 周一到周五)
# /  间隔频率(*/5 = 每5分钟)

常用时间表达式速查

Cron表达式执行时间
0 3 * * *每天凌晨3:00
30 2 * * 0每周日凌晨2:30
0 0 1 * *每月1日零点
*/5 * * * *每5分钟
0 */2 * * *每2小时整点
0 9-18 * * 1-5工作日9:00~18:00每小时
0 3 * * 1,3,5每周一、三、五凌晨3点
@reboot系统重启后执行一次
@daily等同于 0 0 * * *
@weekly等同于 0 0 * * 0

二、Crontab基础操作

<code"># 编辑当前用户的crontab
crontab -e

# 查看当前用户的crontab
crontab -l

# 删除当前用户的crontab
crontab -r

# 以特定用户身份编辑(需要root权限)
crontab -u www-data -e

# 编辑系统级crontab(格式多一列"用户")
nano /etc/crontab

三、常用场景配置实战

场景1:每日自动备份数据库

<code"># 每天凌晨2点备份MySQL数据库
0 2 * * * /usr/local/bin/mysql-backup.sh >> /var/log/mysql-backup.log 2>&1

# mysql-backup.sh内容
#!/bin/bash
DATE=$(date +%Y%m%d)
mysqldump -u root -p'数据库密码' --all-databases | gzip > /backup/db_${DATE}.sql.gz
find /backup -name "db_*.sql.gz" -mtime +30 -delete
echo "$(date): 数据库备份完成"

场景2:定时清理日志文件

<code"># 每周日凌晨3点清理30天前的日志
0 3 * * 0 find /var/log/nginx -name "*.gz" -mtime +30 -delete

# 每天凌晨4点清理临时文件
0 4 * * * find /tmp -type f -mtime +7 -delete

# 每天清理Docker无用镜像和容器
0 5 * * * docker system prune -f >> /var/log/docker-prune.log 2>&1

场景3:Let's Encrypt证书续签

<code"># 每天凌晨3点尝试续签(证书只在剩余30天内才真正续签)
0 3 * * * certbot renew --quiet && systemctl reload nginx

场景4:定时同步文件到备份服务器

<code"># 每小时同步网站文件到备份服务器
0 * * * * rsync -az --delete /var/www/html/ backup-server:/backup/www/ >> /var/log/rsync.log 2>&1

场景5:服务健康检查与自动重启

<code"># /usr/local/bin/health-check.sh
#!/bin/bash

# 检查Nginx是否运行,否则重启
if ! systemctl is-active --quiet nginx; then
    systemctl start nginx
    echo "$(date): Nginx已重启" >> /var/log/health-check.log
fi

# 检查PHP-FPM是否运行
if ! systemctl is-active --quiet php8.1-fpm; then
    systemctl start php8.1-fpm
    echo "$(date): PHP-FPM已重启" >> /var/log/health-check.log
fi

# 检查网站可访问性(HTTP 200)
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost/)
if [ "$HTTP_CODE" != "200" ]; then
    echo "$(date): 网站异常,状态码: $HTTP_CODE" >> /var/log/health-check.log
    # 发送告警通知...
fi
<code"># 每5分钟执行一次健康检查
*/5 * * * * /usr/local/bin/health-check.sh

场景6:WordPresswp-cron替换(提升性能)

<code"># 禁用WordPress内置Cron(每次访问触发,性能差)
# wp-config.php中添加:
# define('DISABLE_WP_CRON', true);

# 改为系统cron定时触发(每15分钟)
*/15 * * * * cd /var/www/html && php wp-cron.php > /dev/null 2>&1

# 或使用WP-CLI
*/15 * * * * /usr/local/bin/wp cron event run --due-now --path=/var/www/html --allow-root

四、Crontab最佳实践

1. 使用绝对路径

<code"># 错误:Cron环境PATH不完整,可能找不到命令
*/5 * * * * python3 /scripts/check.py

# 正确:使用绝对路径
*/5 * * * * /usr/bin/python3 /scripts/check.py

# 或在脚本顶部设置PATH
#!/bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

2. 重定向输出避免邮件堆积

<code"># 默认情况下,Cron会把命令输出发送到root邮件(/var/mail/root会积累大量邮件)
# 将输出重定向到日志文件
0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

# 或完全丢弃输出(不推荐,无法排查问题)
0 3 * * * /usr/local/bin/backup.sh > /dev/null 2>&1

3. 添加任务说明注释

<code"># 每天凌晨2点:备份MySQL数据库(保留30天)
0 2 * * * /usr/local/bin/mysql-backup.sh >> /var/log/mysql-backup.log 2>&1

# 每周日3点:同步文件到异地备份服务器
0 3 * * 0 /usr/local/bin/offsite-backup.sh >> /var/log/offsite.log 2>&1

五、Crontab任务不执行排查

排查步骤清单

<code"># 1. 确认cron服务正在运行
systemctl status cron  # 或 crond(CentOS)

# 2. 查看cron执行日志
grep CRON /var/log/syslog | tail -50
# 或
journalctl -u cron | tail -50

# 3. 确认脚本有执行权限
chmod +x /usr/local/bin/your-script.sh

# 4. 手动测试脚本是否能正常执行
sudo -u root /usr/local/bin/your-script.sh

# 5. 检查脚本中的命令是否使用绝对路径
which python3  # 查找绝对路径
which mysqldump

# 6. 验证cron表达式是否正确
# 使用在线工具:https://crontab.guru/

六、Systemd Timer:现代化的Cron替代

Systemd Timer是比crontab更强大的定时任务方案,支持更精确的时间控制、依赖管理和日志集成:

<code"># /etc/systemd/system/backup.service
[Unit]
Description=每日数据库备份

[Service]
Type=oneshot
ExecStart=/usr/local/bin/mysql-backup.sh
User=root
<code"># /etc/systemd/system/backup.timer
[Unit]
Description=每日凌晨2点触发备份

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true   # 若错过执行时间(如服务器关机),重启后立即补执行

[Install]
WantedBy=timers.target
<code"># 启用并启动Timer
systemctl daemon-reload
systemctl enable backup.timer
systemctl start backup.timer

# 查看所有Timer状态
systemctl list-timers

七、总结

Crontab是服务器自动化运维不可缺少的工具,掌握语法和最佳实践后,可以让大量重复性任务完全自动化。建议关键任务(备份、续签、健康检查)都通过Crontab定时执行,并配合日志记录方便排查问题。IDC.Net的香港VPS系统时间默认UTC+8,与中国大陆时区一致,配置定时任务时无需额外调整时区偏移。

THE END