Linux 定时任务 cron 与 crontab 实战指南
在 Linux 服务器运维中,大量重复性工作都需要按固定节奏自动执行:每天凌晨备份数据库、每小时同步一次文件、每周清理过期日志、每月生成一次报表。靠人工去执行既耗时又容易遗漏,而 cron 就是解决这类需求最经典、最可靠的工具。本文从零讲起,带你掌握 crontab 的写法、常用命令与避坑要点。
一、cron 与 crontab 是什么
cron 是 Linux 系统自带的定时任务守护进程,它 7x24 小时在后台运行,每分钟检查一次有没有到期的任务,到点就自动执行命令或脚本。不同发行版的服务名略有差别:Debian / Ubuntu 上叫 cron,RHEL / CentOS 上叫 crond,本质是同一类服务。
crontab 则是管理定时任务的命令行工具。每个用户都有一份属于自己的任务清单,普通用户只能管理自己的任务,root 用户可以管理所有用户的任务。
# Debian / Ubuntu 查看服务状态
systemctl status cron
# RHEL / CentOS 查看服务状态
systemctl status crond
# 启动并设置开机自启(以 cron 为例)
systemctl start cron
systemctl enable cron
二、时间表达式:五段式
crontab 的每一行就是一条任务,格式为“分 时 日 月 周 命令”,前五段是时间,后面是要执行的命令:
* * * * * command
分 时 日 月 周
各段取值范围如下:
| 字段 | 取值范围 | 说明 |
|---|---|---|
| 分 | 0-59 | 每小时的第几分钟 |
| 时 | 0-23 | 每天的第几个小时 |
| 日 | 1-31 | 每月的第几天 |
| 月 | 1-12 | 每年的第几月 |
| 周 | 0-7 | 每周的第几天,0 和 7 都表示周日 |
时间段里还可以使用四种特殊符号:星号表示任意值,逗号表示枚举多个值,短横线表示连续区间,斜杠表示步长。几个例子:
0 2 * * * # 每天凌晨 2 点执行
*/10 * * * * # 每 10 分钟执行一次
0 9,18 * * 1-5 # 每周一到周五的 9 点和 18 点执行
0 0 1 * * # 每月 1 号 0 点执行
30 6 * * 0 # 每周日早上 6:30 执行
注意“日”和“周”是“或”的关系:如果一行里同时写了日和周,只要其中一个条件满足就会执行,这一点经常被新手误解。
三、crontab 常用命令
crontab -e # 编辑当前用户的定时任务(默认用 vi 打开)
crontab -l # 列出当前用户的全部定时任务
crontab -r # 删除当前用户的全部定时任务,操作前务必确认
crontab -l -u zhangsan # root 查看指定用户的任务
编辑器默认是 vi,不熟悉 vi 的朋友可以在执行 crontab -e 之前先设置 export EDITOR=nano,改用 nano 编辑,会友好很多。修改保存后立即生效,不需要重启 cron 服务。
四、实战示例
1. 每天凌晨备份数据库
0 2 * * * /usr/bin/mysqldump -u root -p'密码' mydb > /data/backup/mydb_$(date +\%Y\%m\%d).sql
用 $(date +%Y%m%d) 让文件名带上日期,便于按天归档;注意 crontab 里百分号有特殊含义,必须写成 % 转义。
2. 每周清理过期日志
0 3 * * 0 find /var/log/app -name "*.log" -mtime +30 -delete
每周日凌晨 3 点删除 30 天前的应用日志,避免磁盘被旧日志撑爆。
3. 每 5 分钟做一次服务健康检查
*/5 * * * * curl -fsS http://127.0.0.1:8080/health || systemctl restart myapp
接口不通时自动重启服务,是最简单的自愈手段。
4. 每月 1 号生成报表并记录日志
0 8 1 * * /opt/report/monthly.sh >> /var/log/report.log 2>&1
五、输出与日志管理
cron 执行任务产生的标准输出和错误,默认会通过邮件发给任务所属用户,服务器上往往没有配置邮件服务,结果就是输出被丢弃。正确做法是每条任务都重定向到日志文件:
0 2 * * * /opt/backup.sh >> /var/log/backup.log 2>&1
两个大于号追加标准输出,2>&1 把错误输出也合并进去。这样任务每次执行的结果都有据可查,出问题直接看日志即可定位。
排查时还可以查看系统日志:
# Debian / Ubuntu
grep CRON /var/log/syslog
# RHEL / CentOS
grep CROND /var/log/cron
如果任务到了时间却没有执行,先在这两个地方确认 cron 有没有尝试运行它。
六、五个常见的坑
1. 环境变量缺失。 cron 执行时只带了极少的环境变量,PATH 里可能没有 /usr/local/bin 这类路径,交互 shell 里能跑通的命令,放到 crontab 里就报 command not found。解决办法:命令写绝对路径,或在脚本开头显式 export PATH。
2. 使用了相对路径。 cron 任务的工作目录通常是用户家目录,脚本里写 ./data 之类的相对路径一定会跑偏。脚本里所有路径一律写绝对路径。
3. 百分号未转义。 在 crontab 里,百分号会被当作换行符处理,date +%Y%m%d 必须写成 date +%Y%m%d。
4. 权限问题。 脚本需要有可执行权限(chmod +x),且运行任务的用户要对涉及的目录有读写权限;在 root 下能跑的脚本,换到普通用户未必能跑。
5. 时区与夏令时。 服务器时区如果和你的预期不一致(比如容器默认 UTC),任务就会在“错误”的时间执行。先用 date 命令确认服务器当前时间,必要时用 timedatectl set-timezone Asia/Shanghai 统一时区。
七、进阶:systemd timer
在较新的发行版上,systemd timer 也可以实现定时任务,支持按秒级调度、依赖启动顺序、失败重试等 cron 做不到的能力:
systemctl list-timers --all # 查看所有 timer
不过对绝大多数日常需求而言,cron 简单可靠、随处可用,仍然是首选;只有当任务需要复杂的依赖关系和重试策略时,才值得迁移到 systemd timer。
八、小结
- cron 是 Linux 定时任务的标准方案,crontab 用于管理任务清单;
- 时间表达式是“分 时 日 月 周”五段式,配合星号、逗号、短横线、斜杠四个符号可以覆盖绝大多数调度需求;
- 每条任务都要重定向输出到日志文件,方便事后排查;
- 写脚本时牢记:绝对路径、转义百分号、检查权限、确认时区。
把这些要点落到自己的服务器上,从一条每天凌晨的备份任务开始,你就拥有了第一份“无人值守”的自动化能力。
- 点赞
- 收藏
- 关注作者
评论(0)