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
然后立即检查日志。
