Linux操作系统-计划任务管理
Linux 计划任务实战:cron、at 与 systemd timer
引言
凌晨三点,你还在睡梦中,服务器却正在自动执行着数据备份、日志清理、证书续期——这些任务不需要任何人守着,全靠计划任务在背后默默工作。
计划任务是 Linux 系统自动化运维的核心能力。如果你还在手动执行那些重复性的定时操作,那这篇文章就是为你准备的。今天我们来彻底搞懂 Linux 计划任务的三大工具:cron(周期性任务)、at(一次性任务)和 systemd timer(现代化的替代方案)。
一、cron:Linux 计划任务的“老大哥”
1.1 什么是 cron?
cron 是 Linux 系统中最经典、最常用的任务调度工具。它以一个名为 crond 的守护进程运行在后台,每分钟醒来一次,检查是否有需要执行的任务。
cron 适合做周期性、重复性的工作,比如:
- 每天凌晨备份数据库
- 每小时同步一次日志
- 每周清理一次过期文件
- 每月生成一份统计报表
1.2 crontab 时间表达式:五个字段定乾坤
cron 的核心是 crontab(cron table 的缩写),也就是任务调度表。每一条 cron 任务都遵循一个固定的格式:
* * * * * command_to_execute
─ ─ ─ ─ ─
│ │ │ │ │
│ │ │ │ └─── 星期 (0-7,0和7都表示周日)
│ │ │ └───── 月份 (1-12)
│ │ └─────── 日期 (1-31)
│ └───────── 小时 (0-23)
└─────────── 分钟 (0-59)
每个时间字段还支持一些特殊符号:
| 符号 | 含义 | 示例 |
|---|---|---|
* |
所有可能的值 | * * * * * 每分钟执行 |
, |
列举多个值 | 1,3,5 表示第1、3、5分钟 |
- |
表示范围 | 9-17 表示9点到17点 |
/ |
表示间隔 | */15 表示每15分钟 |
来看几个实际例子:
# 每天凌晨 3 点执行备份脚本
0 3 * * * /opt/scripts/db_backup.sh
# 每 5 分钟执行一次监控任务
*/5 * * * * /opt/scripts/monitor.sh
# 每周一至周五的上午 9 点到下午 5 点,每半小时执行一次
*/30 9-17 * * 1-5 /usr/bin/log_sync.sh
# 每月 1 号和 15 号的凌晨 3 点执行
0 3 1,15 * * /usr/local/bin/clear_cache.sh
1.3 管理 crontab:增删改查四件套
crontab 命令是管理用户级定时任务的核心工具:
# 编辑当前用户的定时任务(会打开默认编辑器)
crontab -e
# 查看当前用户的所有定时任务
crontab -l
# 删除当前用户的所有定时任务(慎用!)
crontab -r
# 以 root 身份编辑指定用户的定时任务
crontab -u username -e
1.4 用户级 vs 系统级 cron
cron 的任务配置分为两个层级:
用户级 crontab:
- 通过
crontab -e编辑 - 每个用户独立,存储在
/var/spool/cron/目录下 - 适合个人业务任务
系统级 crontab:
- 配置文件位于
/etc/crontab - 格式多了一个“用户”字段:
分 时 日 月 周 用户 命令 - 仅 root 可编辑,适合系统级维护任务
# 系统级 crontab 示例(/etc/crontab)
30 3 * * * root /usr/bin/backup.sh
此外,Linux 还提供了一组预设目录,把脚本放进去就能定时执行:
| 目录 | 执行频率 |
|---|---|
/etc/cron.hourly/ |
每小时 |
/etc/cron.daily/ |
每天 |
/etc/cron.weekly/ |
每周 |
/etc/cron.monthly/ |
每月 |
1.5 权限控制:谁能用 cron?
系统通过两个文件控制用户对 cron 的访问权限:
/etc/cron.allow:白名单,仅列出的用户可用。如果存在,cron.deny被忽略。/etc/cron.deny:黑名单,列出的用户不可用。
默认情况下,/etc/cron.deny 存在但为空(所有人都可以用),/etc/cron.allow 不存在。
# 只允许 user1 使用 cron
echo "user1" > /etc/cron.allow
# 只禁止 user2 使用 cron(需确保 cron.allow 不存在)
echo "user2" > /etc/cron.deny
二、at:只执行一次的“一次性任务”
不是所有任务都需要反复执行。如果你只是想在某个特定时间点执行一次某个操作,at 命令是更好的选择。
2.1 基本用法
at 的语法非常简洁:
at [时间]
输入命令后按 Ctrl+D 结束输入,任务就会被调度。
时间可以写成多种形式:
# 绝对时间
at 23:00 # 今晚 11 点
at 3:00 PM # 下午 3 点
at 2026-07-05 02:00 # 指定日期
# 相对时间
at now + 30 minutes # 30 分钟后
at now + 1 hour # 1 小时后
at now + 2 days # 2 天后
# 特殊关键词
at midnight # 午夜
at noon # 中午 12 点
2.2 实战示例
# 今晚 11 点关机
at 23:00
shutdown now
Ctrl+D
# 30 分钟后创建一个测试文件
at now + 30 minutes
touch /tmp/test.txt
Ctrl+D
# 凌晨 2 点执行备份脚本
at 2:00 AM
/opt/scripts/backup.sh
Ctrl+D
2.3 管理 at 任务
# 查看所有待执行的一次性任务
atq
# 输出示例:
# 2 Fri Jan 13 23:00:00 2025 a user
# 删除指定任务(按任务编号)
atrm 2
# 或者使用别名
at -l # 等同于 atq
at -d 2 # 等同于 atrm 2
2.4 启用 at 服务
at 命令依赖 atd 守护进程:
# 检查 atd 服务状态
systemctl status atd
# 启动并启用 atd
systemctl start atd
systemctl enable atd
# 如果未安装,先安装
# Ubuntu/Debian
sudo apt install at
# CentOS/RHEL
sudo yum install at
2.5 at 的权限控制
和 cron 类似,at 也通过 at.allow 和 at.deny 控制用户访问。如果两个文件都不存在,则只有 root 用户可以使用 at。
💡 cron vs at 一句话总结:cron 管“重复”,at 管“一次”。周期性任务用 cron,临时性的一次性任务用 at。
三、systemd timer:cron 的现代化接班人
随着 systemd 在 Linux 生态中的全面普及,systemd timer 正逐渐成为 cron 的有力竞争者,甚至可以说是替代方案。
3.1 为什么要用 systemd timer?
相比 cron,systemd timer 有几个显著优势:
| 优势 | 说明 |
|---|---|
| 日志集中 | 通过 journalctl 统一查看,排错方便 |
| 依赖管理 | 可以定义任务之间的依赖关系 |
| 服务集成 | 与 systemd 服务深度绑定,管理更规范 |
| 精度更高 | 支持毫秒级精度 |
| 持久化 | 错过执行时间后可以补执行 |
3.2 核心概念:Service + Timer 双文件
systemd timer 由两个配置文件组成:
.service文件:定义要执行的具体任务(脚本、命令).timer文件:定义触发时间规则
3.3 实战:用 systemd timer 替代 cron
假设我们要每天凌晨 3 点执行数据库备份。
第一步:创建 Service 文件
# /etc/systemd/system/db-backup.service
[Unit]
Description=Database Backup Task
[Service]
Type=oneshot
ExecStart=/usr/local/bin/db_backup.sh
User=root
第二步:创建 Timer 文件
# /etc/systemd/system/db-backup.timer
[Unit]
Description=Run database backup daily at 3 AM
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
OnCalendar 支持类似 cron 的语法,也支持更自然的时间表达:
# 每天凌晨 3 点
OnCalendar=daily
# 每周一凌晨 3 点
OnCalendar=Mon *-*-* 03:00:00
# 每 5 分钟
OnCalendar=*:0/5
# 每月 1 号凌晨 3 点
OnCalendar=*-*-01 03:00:00
第三步:启用 Timer
# 重新加载 systemd 配置
systemctl daemon-reload
# 启动 timer
systemctl start db-backup.timer
# 设置开机自启
systemctl enable db-backup.timer
# 查看所有 timer
systemctl list-timers
3.4 查看 systemd timer 日志
这是 systemd timer 相比 cron 最大的优势——日志统一且清晰:
# 查看特定任务的日志
journalctl -u db-backup.service
# 实时跟踪
journalctl -u db-backup.service -f
# 查看最近一天的所有 timer 日志
journalctl --since "1 day ago" | grep timer
四、生产环境最佳实践
4.1 永远使用绝对路径
这是 cron 任务失败最常见的原因。cron 的执行环境与你的交互式 Shell 不同,PATH 环境变量通常很短。
❌ 错误做法:
* * * * * backup.sh # 可能找不到命令
✅ 正确做法:
* * * * * /opt/scripts/backup.sh
或者在 crontab 文件顶部显式设置 PATH:
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
4.2 记录日志,便于排查
cron 任务的输出默认会通过邮件发送给用户(如果邮件系统未配置,输出可能直接丢失)。建议手动重定向日志:
# 将标准输出和错误都写入日志文件
0 3 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
# 分离成功日志和错误日志
0 3 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>> /var/log/backup-errors.log
4.3 防止任务重复执行
如果一个任务执行时间可能超过执行间隔,使用 flock 防止并发执行:
*/5 * * * * flock -n /tmp/task.lock /opt/scripts/task.sh
4.4 最小权限原则
生产环境建议为每个定时任务创建专用用户,避免直接使用 root 权限:
# 以指定用户身份执行
crontab -u backupuser -e
4.5 修改/删除前先备份
删除操作不可逆,建议先备份:
crontab -l > /tmp/cron_backup_$(date +%Y%m%d).cron
crontab -r # 确认备份无误后再删除
4.6 在生产环境部署前充分测试
在测试环境中手动运行命令,验证无误后再配置为定时任务。同时要确认服务器时区是否正确——cron 的执行时间依赖于系统时间。
五、三个工具怎么选?一张表告诉你
| 场景 | 推荐工具 | 原因 |
|---|---|---|
| 每天/每周/每月重复执行 | cron | 经典稳定,语法简单,所有 Linux 默认自带 |
| 只需执行一次的临时任务 | at | 轻量灵活,语法自然 |
| 需要精确日志、依赖管理的复杂任务 | systemd timer | 日志集中、支持依赖、与 systemd 生态集成 |
| 新部署的系统,追求现代化 | systemd timer | 大势所趋,管理更规范 |
📌 一句话建议:日常周期性任务用 cron 就够了;需要精细日志和依赖管理时,切换到 systemd timer;一次性任务直接用 at。
六、常见问题排查清单
Q1:cron 任务没执行,怎么查?
第一步:确认 cron 服务在运行
systemctl status crond
第二步:查看 cron 日志
# Ubuntu/Debian
grep CRON /var/log/syslog | tail -20
# CentOS/RHEL
tail -20 /var/log/cron
# systemd 系统
journalctl -u cron.service -f
第三步:检查语法是否正确
crontab -l # 查看当前配置
Q2:脚本手动能跑,cron 里跑不了?
这通常是因为 环境变量不同。解决方法:
- 在脚本中显式声明
PATH - 在 crontab 顶部设置
PATH - 命令和脚本都使用绝对路径
Q3:at 任务没执行?
# 检查 atd 服务是否运行
systemctl status atd
# 查看待执行任务
atq
# 检查权限配置
cat /etc/at.allow
cat /etc/at.deny
Q4:systemd timer 没触发?
# 查看 timer 状态
systemctl status mytimer.timer
# 列出所有 timer
systemctl list-timers --all
# 查看相关日志
journalctl -u mytimer.service
总结
从 cron 到 at,再到 systemd timer,Linux 计划任务工具走过了一条从分散到统一、从简单到强大的演进之路。
记住三句话:
- cron 管“重复”:周期性任务的首选,经典可靠。
- at 管“一次”:临时性任务,用完即走。
- systemd timer 管“未来”:现代化方案,日志清晰、管理规范。
计划任务是 Linux 自动化运维的基石。掌握了这三个工具,你就能让服务器在无人值守的情况下,有条不紊地完成各种重复性工作——把时间留给更重要的事情。
如果你有任何问题或经验分享,欢迎在评论区留言讨论!
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)