task scheduling manager
cron
,这是 Linux 系统中用于定时执行任务的核心服务,也是实现自动化运维的基石。
cron
- Linux 任务计划调度器
一、cron
概念
- 是什么:
cron
是一个在后台持续运行的守护进程 (daemon),名为crond
。它会根据一个名为crontab
(cron table) 的配置文件,在指定的时间、日期或间隔自动执行预设的命令或脚本。 - 用途:
- 系统维护:定时清理日志文件、更新软件包、检查系统状态。
- 数据处理:定时备份数据库、同步文件、生成报表。
- 应用任务:定时执行爬虫、发送邮件通知、运行批处理作业。
- 监控脚本:定时运行我们之前讨论过的性能监控脚本(如检查内存、磁盘空间)并发送告警。
二、crontab
配置文件
cron
的所有调度规则都定义在 crontab
文件中。每个用户都可以拥有自己的 crontab
文件,此外还有一个系统级的 crontab
文件。
用户
crontab
:- 这是最常用的方式。每个用户定义的任务都以该用户的身份运行。
- 文件通常存储在
/var/spool/cron/
(CentOS/RHEL) 或/var/spool/cron/crontabs/
(Debian/Ubuntu) 目录下,文件名与用户名相同。 - 绝不应该直接编辑这些文件,而应使用
crontab -e
命令。
系统
crontab
:- 文件路径是
/etc/crontab
。 - 这个文件通常由系统管理员维护,用于执行系统级的维护任务。
- 与用户
crontab
不同,它的语法需要在命令前指定运行该命令的用户名。
- 文件路径是
预设的
cron
目录:- 很多系统还提供了更简单的定时任务配置方式,只需将可执行脚本放入以下目录即可:
/etc/cron.hourly/
: 每小时执行一次。/etc/cron.daily/
: 每天执行一次。/etc/cron.weekly/
: 每周执行一次。/etc/cron.monthly/
: 每月执行一次。
- 很多系统还提供了更简单的定时任务配置方式,只需将可执行脚本放入以下目录即可:
三、crontab
命令
这是管理用户 crontab
文件的标准工具。
crontab -e
: 编辑当前用户的crontab
文件。第一次运行时,可能会让你选择一个默认的文本编辑器(如nano
,vim
)。crontab -l
: 列出当前用户的所有cron
任务。crontab -r
: 移除当前用户的所有cron
任务。这个命令非常危险,会不经确认直接删除所有任务,请谨慎使用!crontab -u <username> -e
: (需要 root 权限) 编辑指定用户的crontab
文件。
四、crontab
语法
crontab
的每一行都代表一个定时任务,其格式如下:
1 | # ┌───────────── 分钟 (0 - 59) |
特殊字符的含义:
*
(星号): 代表该字段的每一个可能值。例如,分钟字段的*
表示“每分钟”。,
(逗号): 用于分隔一个列表。例如,1,15,30
在分钟字段表示第 1、15、30 分钟。-
(连字符): 用于表示一个范围。例如,9-17
在小时字段表示从早上 9 点到下午 5 点的每个小时。/
(斜杠): 用于指定步长(间隔)。例如,*/5
在分钟字段表示“每 5 分钟”。它等同于0,5,10,15,...
。
五、实战示例
每天凌晨 2:15 清理临时文件:
1
15 2 * * * /usr/bin/rm -rf /tmp/*
每周日凌晨 4:30 执行数据库备份脚本:
1
30 4 * * 0 /home/mugster/scripts/backup_mysql.sh
(这里的
0
代表星期日)工作日的每天下午 6 点整发送报告:
1
0 18 * * 1-5 /home/mugster/scripts/send_report.py
(这里的
1-5
代表星期一到星期五)每隔 10 分钟检查一次网站健康状态:
1
*/10 * * * * /usr/bin/curl -s --head http://yourwebsite.com || /home/mugster/scripts/notify_admin.sh
(如果
curl
命令失败,则执行通知脚本)每月 1 号的凌晨 0 点 0 分执行月度归档任务:
1
0 0 1 * * /home/mugster/scripts/monthly_archive.sh
六、运维中的重要注意事项
使用绝对路径:
cron
执行任务时的环境变量非常有限,可能找不到你登录时可以正常使用的命令。因此,在crontab
中,所有命令和脚本都应使用绝对路径。可以用which <command>
来查找命令的绝对路径。重定向输出:默认情况下,
cron
任务的任何输出(标准输出和标准错误输出)都会以邮件形式发送给任务的所有者。为了避免产生大量不必要的邮件,通常需要重定向输出:- 不关心输出:这会将标准输出 (
1
* * * * * /path/to/command > /dev/null 2>&1
>
) 和标准错误输出 (2>&1
) 都重定向到“黑洞”设备/dev/null
。 - 记录到日志文件:
1
* * * * * /path/to/command >> /var/log/my_cron_job.log 2>&1
>>
表示追加到日志文件,而不是覆盖。
- 不关心输出:
权限问题:
cron
任务是以其所有者的身份运行的。确保该用户对要执行的脚本有执行权限 (chmod +x /path/to/script.sh
),并且对脚本中涉及的所有文件和目录有正确的读写权限。%
符号的转义:在crontab
的命令部分,%
符号有特殊含义,会被转换成换行符。如果你需要使用%
(例如在date
命令的格式化字符串中),你需要用反斜杠\
进行转义。1
2
3
4# 错误
0 * * * * cp /var/log/app.log /backups/app-$(date +%Y-%m-%d).log
# 正确
0 * * * * cp /var/log/app.log /backups/app-$(date +\%Y-\%m-\%d).log
cron
是 Linux 系统自动化的核心,理解并熟练使用它,是每一位系统管理员和运维工程师的必备技能。
systemd timer
这是 systemd
体系中用于替代传统 cron
的现代化任务调度机制。它功能更强大、日志更完善、依赖关系管理更灵活。
systemd timer
- 新一代的 Linux 定时任务管理器
一、systemd timer
概念与优势
- 是什么:
systemd timer
是一种systemd
的单元 (unit) 类型,文件名以.timer
结尾。它不直接执行任务,而是像一个闹钟,在指定的时间被激活 (trigger),然后去启动另一个与之配对的systemd
单元(通常是一个.service
单元)。 - 核心理念:将“何时执行” (timer) 与“执行什么” (service) 解耦。
- 相比
cron
的优势:- 日志记录超强:所有
timer
触发的服务的输出都会自动被journald
捕获,可以通过journalctl
轻松查看任务是否成功、输出是什么、错误信息是什么,无需手动重定向。 - 依赖与顺序管理:可以精确定义任务在系统启动后多久、在某个网络服务可用后、或在某个挂载点就绪后才开始执行。这是
cron
难以做到的。 - 灵活性更高:支持更复杂的定时规则,如“开机后 5 分钟”、“上次运行后 1 小时”等,并且可以为不同的定时器设置不同的精确度。
- 资源控制:由于任务是通过
.service
文件执行的,因此可以利用systemd
强大的资源控制能力(Cgroups),限制任务的 CPU、内存使用量。 - 易于管理和调试:可以使用标准的
systemctl
命令来控制(启动、停止、查看状态)定时任务,就像管理普通服务一样。
- 日志记录超强:所有
二、systemd timer
的组成部分
一个完整的 systemd timer
任务通常由两个文件组成,它们的文件名(除后缀外)必须相同。
.timer
文件 (定义何时执行)- 作用:描述定时规则。
- 存放路径:
- 系统级:
/etc/systemd/system/
- 用户级:
~/.config/systemd/user/
- 系统级:
- 关键配置段:
[Unit]
:Description
描述信息。[Timer]
: 核心部分,定义时间。OnCalendar=
: 基于日历的绝对时间,语法类似cron
但更灵活。OnBootSec=
: 系统启动后多长时间执行。OnStartupSec=
:systemd
进程启动后多长时间执行。OnUnitActiveSec=
: 该timer
单元上次被激活后多长时间执行。Persistent=true
: 如果系统在timer
应该触发时处于关机状态,那么在下次开机后立即补偿执行一次错过的任务。RandomizedDelaySec=
: 随机延迟,避免大量任务在同一精确时刻同时执行,造成系统负载尖峰(Thundering Herd Problem)。
[Install]
:WantedBy=timers.target
表示这个timer
应该被timers.target
管理。
.service
文件 (定义做什么)- 作用:描述要执行的具体命令或脚本。
- 存放路径:与
.timer
文件相同。 - 关键配置段:
[Unit]
:Description
描述信息,可以定义依赖关系(如After=network.target
)。[Service]
: 核心部分,定义执行的动作。Type=oneshot
: 表示这是一个一次性执行的任务,而不是长期运行的服务。ExecStart=
: 指定要执行的命令或脚本的绝对路径。
三、OnCalendar
语法详解
OnCalendar
的格式非常灵活:DayOfWeek Year-Month-Day Hour:Minute:Second
- 可以省略前面的部分,例如
HH:MM:SS
表示每天的这个时间。 *
: 通配符,表示每个值。,
: 列表分隔符,例如Mon,Wed,Fri
。-
: 范围,例如9-17
。/
: 步长,例如*:0/15
表示每 15 分钟。- 预设别名:
minutely
,hourly
,daily
,weekly
,monthly
,yearly
。
对比 cron
的示例:
描述 | cron 语法 | systemd OnCalendar 语法 |
---|---|---|
每分钟 | * * * * * | minutely 或 *-*-* *:*:00 |
每 5 分钟 | */5 * * * * | *:0/5 |
每天凌晨 2:30 | 30 2 * * * | daily (不精确)或 02:30:00 |
周一早上 9 点 | 0 9 * * 1 | Mon *-*-* 09:00:00 |
四、实战:创建一个 systemd timer
任务
目标:创建一个系统级的定时任务,每 5 分钟清理一次 /tmp
目录,并在网络可用后才执行。
第一步:创建 .service
文件
使用文本编辑器(如 nano
或 vim
)创建文件:如何知道systemd的配置文件在哪
1 | sudo nano /etc/systemd/system/cleanup-tmp.service |
写入以下内容:
1 | [Unit] |
第二步:创建 .timer
文件
文件名必须与 .service
文件匹配:
1 | sudo nano /etc/systemd/system/cleanup-tmp.timer |
写入以下内容:
1 | [Unit] |
第三步:管理和启用 timer
重新加载
systemd
配置:1
sudo systemctl daemon-reload
**启动并启用
timer
**(注意,我们操作的是.timer
文件,不是.service
文件!):1
2
3
4
5# 立即启动 timer,让它开始计时
sudo systemctl start cleanup-tmp.timer
# 设置 timer 开机自启
sudo systemctl enable cleanup-tmp.timer
第四步:验证和调试
**列出所有活动的
timer
**:1
systemctl list-timers
你应该能看到
cleanup-tmp.timer
,以及它下一次触发的时间 (NEXT
) 和距离现在的时间 (LEFT
)。查看
timer
的状态:1
systemctl status cleanup-tmp.timer
查看
service
的执行日志:
当timer
触发过service
后,你可以用journalctl
查看日志。1
2
3
4
5# 查看关联服务的日志
journalctl -u cleanup-tmp.service
# 持续关注日志
journalctl -u cleanup-tmp.service -f手动触发一次任务进行测试:
如果你不想等待定时器触发,可以手动运行.service
文件来测试命令是否正确。1
sudo systemctl start cleanup-tmp.service
然后立即检查日志。