Linux Cron + Shell 定时运行脚本完全指南
一、Cron 简介
Cron 是 Linux/Unix 系统中最常用的定时任务工具,可以按照预设的时间规律自动执行命令或脚本。
二、安装 Cron
1. 检查是否已安装
# 检查 cron 服务状态systemctl status cron # Debian/Ubuntusystemctl status crond # CentOS/RHEL/Fedora# 或检查进程ps aux | grep cron
2. 根据不同发行版安装
Debian/Ubuntu:
sudo apt updatesudo apt install cron -y
CentOS/RHEL 7+:
sudo yum install cronie -y
CentOS/RHEL 8+/Fedora:
sudo dnf install cronie -y
Arch Linux:
sudo pacman -S cronie
3. 启动并设置开机自启
# Debian/Ubuntusudo systemctl start cronsudo systemctl enable cron# CentOS/RHELsudo systemctl start crondsudo systemctl enable crond# 查看状态sudo systemctl status cron # 或 crond
三、编写第一个 Shell 脚本
1. 创建脚本文件
# 创建脚本存放目录mkdir -p ~/scripts# 创建备份脚本示例nano ~/scripts/backup.sh
2. 脚本示例:系统备份
#!/bin/bash# ============================================# 脚本名称: backup.sh# 功能描述: 备份指定目录到备份文件夹# 作者: System Admin# 创建日期: 2024-01-01# ============================================# 配置参数BACKUP_SOURCE="/home/$USER/documents"BACKUP_DEST="/home/$USER/backups"LOG_FILE="/home/$USER/backup.log"MAX_BACKUPS=7 # 保留最近7个备份DATE=$(date +"%Y%m%d_%H%M%S")# 创建备份目录(如果不存在)mkdir -p "$BACKUP_DEST"# 开始备份echo "[$(date +'%Y-%m-%d %H:%M:%S')] 开始备份任务" >> "$LOG_FILE"# 执行备份if tar -czf "$BACKUP_DEST/backup_$DATE.tar.gz" "$BACKUP_SOURCE" 2>/dev/null; then
echo "[$(date +'%Y-%m-%d %H:%M:%S')] ✓ 备份成功: backup_$DATE.tar.gz" >> "$LOG_FILE"
# 删除旧备份(保留最近 MAX_BACKUPS 个)
cd "$BACKUP_DEST"
ls -t backup_*.tar.gz 2>/dev/null | tail -n +$((MAX_BACKUPS + 1)) | xargs -r rm
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 清理完成,保留最近 $MAX_BACKUPS 个备份" >> "$LOG_FILE"else
echo "[$(date +'%Y-%m-%d %H:%M:%S')] ✗ 备份失败,请检查源路径" >> "$LOG_FILE"
exit 1fiecho "----------------------------------------" >> "$LOG_FILE"exit 0
3. 脚本示例:监控磁盘使用率
#!/bin/bash# disk_monitor.sh - 磁盘使用率监控脚本THRESHOLD=80 # 告警阈值 80%EMAIL="admin@example.com" # 接收告警邮箱LOG="/home/$USER/disk_monitor.log"echo "[$(date +'%Y-%m-%d %H:%M:%S')] 检查磁盘使用率" >> "$LOG"# 获取根分区使用率(去掉 % 符号)USAGE=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')if [ "$USAGE" -gt "$THRESHOLD" ]; then
MESSAGE="警告:根分区使用率已达到 ${USAGE}%,超过阈值 ${THRESHOLD}%"
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $MESSAGE" >> "$LOG"
# 发送邮件(需要配置 mail 服务)
echo "$MESSAGE" | mail -s "磁盘告警 - $(hostname)" "$EMAIL"else
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 当前使用率: ${USAGE}%,正常" >> "$LOG"fi4. 赋予脚本执行权限
chmod +x ~/scripts/backup.shchmod +x ~/scripts/disk_monitor.sh# 验证权限ls -l ~/scripts/
5. 手动测试脚本
# 手动运行测试~/scripts/backup.sh# 查看日志cat ~/backup.log
四、配置 Cron 定时任务
1. Crontab 语法基础
分钟(0-59) 小时(0-23) 日(1-31) 月(1-12) 星期(0-7,0和7都表示周日) 命令
常用时间示例:
| 表达式 | 含义 |
|---|
* * * * * | 每分钟执行 |
*/5 * * * * | 每5分钟执行 |
0 * * * * | 每小时整点执行 |
0 2 * * * | 每天凌晨2点执行 |
0 2 * * 0 | 每周日凌晨2点执行 |
0 2 1 * * | 每月1号凌晨2点执行 |
0 2 1 1 * | 每年1月1日凌晨2点执行 |
2. 编辑用户定时任务
# 编辑当前用户的 crontabcrontab -e# 如果是第一次使用,会提示选择编辑器,选择 nano 或 vim 即可
3. 添加定时任务
在打开的 crontab 文件中添加以下内容:
# ============================================# 我的定时任务配置# ============================================# 设置环境变量(可选)SHELL=/bin/bashPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binMAILTO=your-email@example.com # 错误输出发送到此邮箱# 1. 每天凌晨2点执行备份脚本0 2 * * * /home/username/scripts/backup.sh# 2. 每30分钟检查一次磁盘(早上8点到晚上8点)*/30 8-20 * * * /home/username/scripts/disk_monitor.sh# 3. 每周一早上9点清理临时文件0 9 * * 1 find /tmp -type f -atime +7 -delete 2>/dev/null# 4. 每月1号凌晨3点执行数据库备份0 3 1 * * /home/username/scripts/db_backup.sh# 5. 每5分钟记录系统负载*/5 * * * * echo "$(date) - Load: $(uptime | awk -F'load average:' '{print $2}')" >> /home/username/load.log# 6. 每天重启一次特定服务(示例)0 4 * * * sudo systemctl restart nginx4. 常用 Crontab 命令
# 查看当前用户的定时任务crontab -l# 编辑定时任务crontab -e# 删除所有定时任务crontab -r# 删除前确认crontab -i -r# 查看其他用户的定时任务(需要root权限)sudo crontab -u otheruser -l
五、高级技巧
1. 重定向输出
# 标准输出和错误输出都追加到日志文件0 2 * * * /home/username/scripts/backup.sh >> /var/log/backup.log 2>&1# 丢弃所有输出(不推荐,排错困难)0 2 * * * /home/username/scripts/backup.sh > /dev/null 2>&1# 只记录错误输出0 2 * * * /home/username/scripts/backup.sh >> /var/log/backup.log 2>&1
2. 使用 @ 快捷符号
@reboot # 系统启动时执行一次@yearly # 每年1月1日 00:00 (0 0 1 1 *)@annually # 同 @yearly@monthly # 每月1日 00:00 (0 0 1 * *)@weekly # 每周日 00:00 (0 0 * * 0)@daily # 每天 00:00 (0 0 * * *)@hourly # 每小时整点 (0 * * * *)
示例:
# 系统启动后等待30秒执行脚本@reboot sleep 30 && /home/username/scripts/startup.sh# 每天执行一次@daily /home/username/scripts/daily_task.sh
3. 脚本中的最佳实践
#!/bin/bash# 健壮的脚本模板# 获取脚本所在目录(用于相对路径)SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"# 设置锁定文件,防止重复执行
LOCK_FILE="/tmp/$(basename "$0").lock"# 检查是否已有实例运行
if [ -e "$LOCK_FILE" ]; then
echo "脚本已在运行中,退出"
exit 1
fi
# 创建锁定文件
trap "rm -f $LOCK_FILE" EXITtouch "$LOCK_FILE"# 脚本主逻辑# ... 你的代码 ...# 退出时自动删除锁定文件exit 04. 系统级定时任务
# 系统级 crontab 文件位置/etc/crontab # 系统主配置文件/etc/cron.d/ # 额外的配置目录/etc/cron.hourly/ # 每小时执行的脚本目录/etc/cron.daily/ # 每天执行的脚本目录/etc/cron.weekly/ # 每周执行的脚本目录/etc/cron.monthly/ # 每月执行的脚本目录
创建系统级任务示例:
# 创建脚本并放入相应目录sudo nano /etc/cron.daily/cleanup.sh# 内容#!/bin/bashfind /var/log -name "*.log" -mtime +30 -delete# 赋予执行权限sudo chmod +x /etc/cron.daily/cleanup.sh
六、调试与排错
1. 查看 Cron 日志
# Ubuntu/Debiansudo grep CRON /var/log/syslog# CentOS/RHELsudo journalctl -u crond# 或sudo tail -f /var/log/cron
2. 常见问题解决
问题1:脚本可以手动运行,但 cron 不执行
# 原因1:环境变量不同,使用绝对路径# 错误示例0 2 * * * backup.sh# 正确示例0 2 * * * /home/username/scripts/backup.sh# 原因2:脚本缺少执行权限chmod +x /home/username/scripts/backup.sh# 原因3:脚本中的命令也需要绝对路径# 在脚本开头添加PATH=/usr/local/bin:/usr/bin:/bin
问题2:调试方法
# 在 crontab 中临时添加调试输出* * * * * /home/username/scripts/test.sh >> /tmp/cron_debug.log 2>&1# 测试 cron 语法(使用在线工具或本地检查)# 每5分钟执行:*/5 * * * * command
3. 可视化 Crontab 管理工具
# 安装 Crontab UI (Web界面)# 注意:生产环境谨慎使用# 或使用 crontab.guru 网站验证语法# https://crontab.guru/
七、完整示例:自动备份网站
#!/bin/bash# /home/username/scripts/website_backup.sh# 配置WEB_ROOT="/var/www/html"BACKUP_DIR="/backup/website"DATE=$(date +%Y%m%d_%H%M%S)DB_NAME="mydatabase"DB_USER="root"DB_PASS="password"RETENTION_DAYS=30# 创建备份目录mkdir -p "$BACKUP_DIR"# 备份文件echo "[$(date)] 开始备份网站文件..."tar -czf "$BACKUP_DIR/files_$DATE.tar.gz" "$WEB_ROOT" 2>/dev/null# 备份数据库echo "[$(date)] 开始备份数据库..."mysqldump -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" > "$BACKUP_DIR/db_$DATE.sql"# 压缩数据库备份gzip "$BACKUP_DIR/db_$DATE.sql"# 删除过期备份find "$BACKUP_DIR" -name "files_*.tar.gz" -mtime +$RETENTION_DAYS -deletefind "$BACKUP_DIR" -name "db_*.sql.gz" -mtime +$RETENTION_DAYS -deleteecho "[$(date)] 备份完成!"
添加 Crontab:
# 每天凌晨2点执行网站备份0 2 * * * /home/username/scripts/website_backup.sh
八、安全建议
最小权限原则:脚本只授予必要的执行权限
敏感信息保护:不要在脚本中硬编码密码,使用配置文件并限制权限
chmod 600 ~/.backup_config
日志管理:定期清理日志文件,避免占满磁盘
监控告警:为重要任务配置失败告警
测试环境验证:先在测试环境运行 cron 任务
总结
通过本指南,你已经学会了:
Cron 的安装和配置
Shell 脚本的编写和执行权限设置
Crontab 语法和常用时间表达式
日志记录和调试技巧
最佳实践和安全建议
现在你可以开始使用 Cron + Shell 自动化你的日常运维任务了!