Linux 的例行性工作
1.1 应用场景

生活中,我们有太多场景需要使用到闹钟,比如早上 7 点起床,下午 4 点开会,晚上 8 点购物,等等。
在 Linux 系统里,我们同样也有类似的需求。比如我们想在凌晨 1 点将文件上传服务器,或者在晚 上 10 点确认系统状态等等。
但我们不可能一直守在电脑前,毕竟我们也需要下班 / 睡觉,而且即使在上班期间,如果到点了还需要人 工操作,未免效率太低了。所以计划任务应运而生。
通过设置计划任务可以让服务器在指定时间执行指定命令。
1.2 单一执行的例行性任务 --at (一次性)
1.2.1 安装
at 命令需要安装
运行
bash
[root@server ~]# yum install at -y
[root@server ~]# at -V # 大写V
at version 3.2.2

启动服务
bash
[rootserver -]# systemct] start atd 将某个文件做个备份:cp
[rootserver -]# systemctl enable--now
[rootserver-]#systect1 status atd 查看状态 atd开机启动

1.2.2 at 命令详解
at 命令执行过程
第一步:寻找 /etc/at.allow (白名单) 是否存在,写在该文件中用户才可执行 at 命令
第二步:若 /etc/at.allow 不存在,则寻找 /etc/at.deny (黑名单) 文件,写在该文件中的用户不能使用 at 命令
第三步:若两个文件都不存在则只有 root 用户可以使用 at 命令


格式
at - 参数
日期时间
-m: 当任务完成后,即使没有标准输出,也会给用户发送邮件
-l: 列出系统上所有用户的 at 任务,等价于 atq
-d: 删除或取消一个任务
-v: 使用时间格式,列出 at 任务
-c: 可以列出任务之后的命令内容
-f: 从文件中读取
时间格式
表格
| 参数 | 说明 |
|---|---|
| HH:MM | 在今天 HH 小时的 MM 分钟执行,若时间点错过,将在明天执行 |
| HH:MM YYYY-MM-DD | 规定在某年某月的某一天的特殊时刻执行该工作 (不能写过去的时间) |
| now +2 minutes | 从现在开始的 minutes 、 hours 、 days 、 weeks 执行 |
1.2.3 实验
实验 1
延迟执行 ls /root , 并将结果写入到 at.txt 中
运行
bash
[root@server ~]# at 14:17
warning: commands will be executed using /bin/sh
at> ls /root > at.txt
at> <EOT> # 点击ctrl+d 结束交互性界面
[root@server ~]# at -l # 查看已存在的计划任务
3 Thu May 25 14:17:00 2023 a root
[root@server ~]# atq # 同上,q是查询的意思
3 Thu May 25 14:17:00 2023 a root
注意
at 命令只要指定的时间正确,就可以执行对应的命令
at 命令的输出结果不会显示到屏幕上
at 命令中执行的命令最好使用绝对路径,不容易报错
at 命令只会执行一次
实验 2
不使用交互性命令实现,通过管道符命令执行
运行
bash
[root@server ~]# echo "echo 'hello again' >> at.txt" | at now +1 minute
now +1 minute


实验 3
设置某账户 at 命令不可用
运行
bash
[root@server ~]# useradd ce1 # 新建账户
[root@server ~]# passwd ce1 # 设置密码
更改用户 ce1 的密码 。
新的密码: # 123
无效的密码: 密码少于 8 个字符
重新输入新的密码: # 123
passwd:所有的身份验证令牌已经成功更新。
[root@server ~]# tail -1 /etc/passwd # 倒叙查看账户管理文件
ce1:x:1001:1001::/home/ce1:/bin/
[root@server ~]# vim /etc/at.deny # 设置黑名单
# 输入
ce1
[root@server ~]# su - ce1 # 切换账户
[ce1@server ~]$ at 14 # 测试,at命令不可用
You do not have permission to use at.
查看任务执行日志:
运行
bash
[root@rhel93 ~]# tail -f /var/log/cron
1.3 循环执行的例行性任务 --crontab (周期性)
1.3.1 crond 服务

at 命令是在指定的时间只能执行一次任务,crontab 命令可以循环重复的执行定时任务
crond 是 Linux 下用来周期地执行某种任务或等待处理某些事件的一个守护进程,在安装完成操作 系统后,默认会安装 crond 服务工具,且 crond 服务默认就是自启动的,若需要安装则执行如下
运行
bash
[root@server ~]# yum install crontabs # 安装,注意包名
[root@server ~]# systemctl status crond # 查看状态
crond 进程每分钟会定期检查是否有要执行的任务,如果有,则会自动执行该任务,crontab 命令 需要 crond 服务支持
linux 任务调度的工作主要分为以下两类:
系统执行的工作:系统周期性所要执行的工作,如备份系统数据、清理缓存
个人执行的工作:某个用户定期要做的工作,例如每隔 10 分钟检查邮件服务器是否有新信,这些工作可由每个用户自行设置
1.3.2 crontab 工作过程
当系统中有 /etc/cron.allow 文件时,只有写入此文件的用户可以使用 crontab 命令,没有写入的 用户不能使用 crontab 命令。同样,如果有此文件,/etc/cron.deny 文件会被忽略,因为 /etc/cron.allow 文件的优先级更高
当系统中只有 /etc/cron.deny 文件时,写入此文件的用户不能使用 crontab 命令,没有写入文件 的用户可以使用 crontab 命令
crontab 执行的每一项工作都会被记录到 /var/log/cron 这个日志文件中
当用户使用 crontab 新建工作之后,该项工作就会被记录到 /var/spool/cron/ 目录里面
1.3.3 crontab 命令详解
格式
crontab [-u user] [-l| -r | -e]
表格
| 参数 | 解释 | 示例 |
|---|---|---|
| -l | list 查看定时任务 | crontab -l |
| -e | edit 编辑定时任务,建议手动编辑 | crontab -e |
| -i | 删除定时任务,提示用户确认删除,避免出错 | crontab -i |
| -r | 删除定时任务,移除 /var/spool/cron/username 文件 | crontab -r |
| -u user | 指定用户执行任务,root 可以管理普通用户计划任务 | crontab -u redhat -l |
执行 crontab 命令就是在修改 /var/spool/cron 中的定时任务文件。
编辑 crontab
运行
bash
[root@server ~]# crontab -e
-e
写入的命令格式:每一行书写一个工作,每个工作共有 6 个字段
# 示例
*/5 6-8 * 8 1 /bin/ /test.sh
表格
| 代表意义 | 分钟 | 小时 | 日期 | 月份 | 星期 | 命令 |
|---|---|---|---|---|---|---|
| 数字范围 | 0-59 | 0-23 | 1-31 | 1-12 | 0-7 (0 和 7 表示周日) | 执行的动作 |
表格
| 时间格式中的特殊字符 | 含义 |
|---|---|
| * | 任意时刻 |
| - | 表示时间范围 |
| ,(逗号) | 分割时段 |
| */ 数字 | 指定时间间隔的频率,如:每 3 分钟执行一次,*/3 |
例
表格
| 时间 | 含义 |
|---|---|
| 1 2 * * * | 每天凌晨 2 点零 1 分执行动作 |
| 0 17 * * 1 | 每周一下午 17 点整执行动作 |
| 0 5 1,15 * * | 每月的 1 号和 5 号凌晨 5 点执行动作 |
| 40 4 * * 1-5 | 每周 1 到周 5 的凌晨 4 点 40 分执行动作 |
| */10 4 * * * | 每天凌晨 4 点每隔 10 分钟执行动作 |
| 3,15 8-11 */2 * * | 每隔 2 天的上午 8 点到 11 点的第 3 分钟和第 15 分钟执行动作 |
| * * * * * | 每个 1 分钟执行一次动作 |

1.3.4 实验

实验 4
设置循环周期性任务
运行
bash
[root@server ~]# crontab -e
-e
*/2 * * * * wall $(date)
注意:crond 服务是自动启动的,crontab 命令只要保存退出后就会生效
查看任务:
运行
bash
[root@master ~]# crontab -l
*/2 * * * * wall $(date)
删除任务
运行[
bash
root@server ~]# crontab -r # 删除
[root@server ~]# crontab -l # 查看列表
no crontab for root
实验 5
让系统在每周 1 凌晨 6 点重启一次
运行
bash
[root@server ~]# crontab -e
0 6 * * 1 /sbin/shutdown -r now
实验 6
设置邮件发送告警功能,每 1 分钟发送一封邮件
qq 邮箱设置:

开启 pop3/SMTP 服务:

复制授权码:
安装邮件服务
运行
bash
[root@server chap04]# yum install s-nail -y
配置邮件服务并测试
先编辑
root@rhel93\~\]#vim /etc/s-nail.rc  ###### 最后一行按 O 进入插入模式  # 修改如下文件中的内容为你的邮件账号 运行   ・设置定时任务  ##### 书写定时任务的注意事项 6 个字段都不能为空,如果不确定则使用 \* 表示任意时间 crontab 命令任务的最小时间单位为分钟,最大有效时间为月,如:2024 年某时执行、3 点 30 分 30 秒这样的时间日期无法被识别 定义时间时,日期和星期最好不要一起出现,由于都是以天为单位,非常让管理员混淆 在定时任务中,不管是写命令还是在脚本中写命令,最好都用绝对路径,相对路径有时会报错 #### 1.3.4 系统级别的计划任务 crond 服务除了会在工作时查看 /var/spool/cron 文件夹下的定时任务文件以外,还会查看 /etc/cron.d 目录中的任务。在 /etc/anacrontab 文件里面定义了每天、每周、每月需要执行 的系统任务。 运行 ```bash [root@server ~] # ls -l /etc/ | grep cron* cron.d # 系统定时任务 cron.daily # 每天的任务 cron.deny # 定时任务黑名单 cron.hourly # 每小时执行的任务 cron.monthly # 每月的定时任务 crontab # 定义任务管理文件 cron.weekly # 每周的定时任务 ``` crontab -e 是每个用户都可以执行的命令,但有时定时任务必须由系统执行,此时就需要编 辑 /etc/crontab 配置文件来实现。 运行 \[root@server \~\]# vim /etc/crontab  仅能通过 root 定义,不可以使用普通账户身份去执行计划任务,在 /etc/crontab 最后一行新增计划 任务即可 ```bash SHELL=/bin/ #指定系统使用哪个命令解释器 PATH=/sbin:/bin:/usr/sbin:/usr/bin #系统执行命令的搜索路径 MAILTO=root # For details see man 4 crontabs # Example of job definition: # .---------------- minute (0 - 59) # | .------------- hour (0 - 23) # | | .---------- day of month (1 - 31) # | | | .------- month (1 - 12) OR jan,feb,mar,apr ... # | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat # | | | | | # * * * * * user-name command to be executed ``` 例 1: 每周二 11 点将时间写入 /t1.txt 文件中 运行 ```bash [root@server ~]# vim /etc/crontab 0 11 * * 2 root date >> /t1.txt ``` 例 2: 每天 6:00 点将日志 /var/log/messages 文件备份到 /backup 目录中,备份后的日志文件名修 改为 logfileYYYY-MM-DD 运行 ```bash [root@server ~]# mkdir /backup # 新建目录 [root@server ~]# vim /etc/crontab # 编辑系统计划任务 0 6 * * * root /bin/cp /var/log/messages /backup/logfile`date +\%Y-\%m-\%d` ``` 注意:可以使用 \* \* \* \* \* 进行测试 反引号 \`\` 表示将引起的内容识别为命令,也可以使用 $() 在 crontab 系统中 % 表示换行,需要增加转义符 \\    ### 1.4 练习 #### 题目: 每分钟执行命令 ```bash crontab -e cmd vim /etc/crontab root cmd ``` 1. 每小时执行 2. 每天凌晨 3 点半和 12 点半执行脚本 3. 每隔 6 小时,相当于 6,12,18,24 点半执行脚本 4. 30 代表半点,8-18/2 表示早上 8 点到下午 18 点之间每隔 2 小时执行脚本 5. 每天晚上 9 点 30 重启 nginx 6. 每月 1 和 10 号凌晨 4 点 45 执行脚本 7. 每周六和周日凌晨 1 点 10 分执行命令 8. 每天 18 点到 23 点之间,且每隔 30 分钟执行一次 9. 每隔一小时执行一次 10. 在 4 月份的周一到周三的上午 11 点执行脚本 11. 每天早上 7 点到上午 11 点且每 2 小时执行一次 12. 每天 6 点执行脚本 13. 每周六凌晨 4 点执行 14. 每周六凌晨 4 点 05 执行 15. 每天 8:40 执行 16. 在每天 10:31 执行 17. 每周一到周五 2:00 执行 18. 每周一到周五 8:00 和 9:00 执行 19. 每天 10:00,16:00 执行 答案: 1. \*/1 \* \* \* \* cmd 2. 0 \* \* \* \* cmd 3. 30 3,12 \* \* \* cmd 4. 30 \*/6 \* \* \* cmd 5. 30 8-18/2 \* \* \* cmd 6. 30 21 \* \* \* /usr/bin/systemctl restart nginx 7. 45 4 1,10 \* \* cmd 8. 10 1 \* \* 6,0 cmd 9. 0,30 18-23 \* \* \* cmd 或 \*/30 18-23 \* \* \* cmd 10. 0 \*/1 \* \* \* cmd 或 0 \* \* \* \* cmd 11. 0 11 \* 4 1-3 cmd 12. 0 7-11/2 \* \* \* cmd 13. 0 6 \* \* \* cmd 14. 0 4 \* \* 6 cmd 15. 5 4 \* \* 6 cmd 16. 40 8 \* \* \* cmd 17. 31 10 \* \* \* cmd 18. 0 2 \* \* 1-5 cmd 19. 0 8,9 \* \* 1-5 cmd 20. 0 10,16 \* \* \* cmd *** ** * ** *** ## 二、小白保姆级解读(0 基础也能秒懂) 很多刚接触 Linux 的小伙伴会问:我想让服务器半夜自己备份数据、凌晨自动更新文件、出问题自动给我发邮件,总不能 24 小时守着电脑吧? 答案就是 Linux 的**例行性工作(定时任务)**!说白了就是给 Linux 系统设「闹钟」,到点就自动干活,核心分两种: * **一次性闹钟**:只在指定时间干一次活(at命令) * **循环闹钟**:每天 / 每周 / 每月重复干活(crontab命令) 下面咱们用生活化的类比,把每个知识点掰碎了讲,避坑指南也给你安排得明明白白! ### 一、先搞懂:Linux 定时任务到底有啥用? 就像咱们生活里的闹钟、外卖预约、每周例会提醒,Linux 的定时任务就是帮你**自动化执行重复 / 指定时间的操作**,不用人工值守。 * 凌晨 1 点没人用服务器的时候,自动备份网站数据 * 每天晚上 10 点,自动检查服务器的运行状态 * 服务器出故障了,自动给你发告警邮件 * 每周一凌晨 6 点,自动重启服务器释放内存 ### 二、一次性定时任务:at 命令(订一次外卖,到点只送一次) at就像你预约一次外卖,只在你指定的时间送一次,送完就结束,不会重复。 #### 1. 先装工具 + 开服务 at不是系统默认自带的,先安装,再启动对应的atd服务(相当于闹钟的后台程序): 运行 ```bash # 安装at命令 yum install at -y # 启动atd服务 systemctl start atd # 设置开机自动启动,重启服务器也不失效 systemctl enable --now atd # 查看服务状态,显示active(running)就是正常 systemctl status atd ``` #### 2. 谁能用 at?黑白名单规则(小区门禁逻辑) 系统会通过两个文件控制用户的使用权限,优先级:**白名单 \> 黑名单 \> 仅 root 可用** 1. 先找/etc/at.allow(白名单):只有写在这个文件里的用户能使用 at,有这个文件,黑名单直接作废 2. 没有白名单,就找/etc/at.deny(黑名单):写在这个文件里的用户不能用,其他人都能用 3. 两个文件都没有?只有超级管理员 root 能使用 小技巧:默认系统只有at.deny且是空的,所以所有用户都能使用 at;想禁止某个用户用,直接把用户名写到at.deny里就行。 #### 3. at 命令怎么用?核心参数 + 时间格式 基础格式:at 时间,输入后进入交互界面,写要执行的命令,按ctrl+d结束并保存。 ##### 核心常用参数 表格 | **参数** | **大白话解释** | |----------|------------------------| | -l / atq | 查看当前所有的 at 定时任务 | | -d 任务号 | 删除指定的 at 任务(不想执行了就删) | | -c 任务号 | 查看这个 at 任务里写的具体命令 | | -m | 任务执行完,哪怕没有输出,也给用户发邮件通知 | ##### 3 种最常用的时间写法 表格 | **写法** | **大白话解释** | |------------------|-----------------------------------------------------| | 14:30 | 今天下午 2 点 30 分执行,要是这个时间已经过了,就明天这个时间执行 | | 14:30 2026-05-20 | 2026 年 5 月 20 日下午 2 点 30 分执行,只能写未来的时间 | | now + 5 minutes | 从现在开始,5 分钟后执行(还能写 hours/days/weeks,比如 now + 2 days) | #### 4. 新手避坑提醒 1. at 命令的执行结果**不会显示在屏幕上**,所以一定要把结果重定向到文件里(比如ls /root \> at.txt),不然你看不到执行结果 2. 命令一定要写**绝对路径**!比如写/bin/ls而不是ls,避免系统找不到命令执行失败 3. at 任务**只执行一次**,执行完就消失了,想重复执行要用 crontab ### 三、循环定时任务:crontab 命令(每天的起床闹钟,到点就响) crontab是 Linux 里最常用的定时任务工具,就像你设置的每天起床闹钟,按周期重复执行,永不过期(除非你删掉)。 #### 1. 先搞懂 crond 服务 crontab 命令的后台程序是crond,系统默认自带且开机自启,它每分钟都会检查一遍有没有要执行的任务,有就自动执行。 运行 ```bash # 没装的话先安装 yum install crontabs -y # 查看服务状态,默认就是active(running) systemctl status crond ``` #### 2. 谁能用 crontab?和 at 一模一样的黑白名单规则 * 白名单/etc/cron.allow:优先级最高,只有名单里的用户能用 * 黑名单/etc/cron.deny:名单里的用户不能用,其他人都能用 * 两个文件都没有:只有 root 能用 * 所有任务的执行日志都存在/var/log/cron里,执行失败了可以去这里查原因 #### 3. crontab 核心:6 字段语法,看完就会写 咱们平时设闹钟,会选「几分、几点、几号、几月、周几」,然后设「到点干啥」,crontab 也是一模一样!**一行一个任务,6 个字段一个都不能少**,顺序固定不能乱: 表格 | **字段 1** | **字段 2** | **字段 3** | **字段 4** | **字段 5** | **字段 6** | | |----------|----------|----------|----------|----------|-------------|----------| | 分钟 | 小时 | 日期 | 月份 | 星期 | 要执行的命令 / 脚本 | | | 取值范围 | 0-59 | 0-23 | 1-31 | 1-12 | 0 和 7 都代表周日 | 必须写绝对路径! | ##### 4 个特殊字符,搞定所有周期 表格 | **特殊字符** | **大白话解释** | **举个例子** | |----------|---------------|----------------------------------| | \* | 任意时刻,「每一个」的意思 | 分钟字段写 \*,就是每分钟都执行 | | - | 连续的时间范围 | 小时字段写 8-18,就是早上 8 点到下午 6 点之间都执行 | | , | 不连续的多个时间点 | 小时字段写 3,12,就是凌晨 3 点和中午 12 点各执行一次 | | \*/n | 每隔 n 个单位执行一次 | 分钟字段写 \*/10,就是每隔 10 分钟执行一次 | #### 4. 新手必看:90% 的人都会踩的坑 1. **6 个字段一个都不能空**!不确定的字段就写 \*,比如不知道几月执行,月份字段就写 \* 2. **最小时间单位是分钟**,不能设秒级任务(比如 30 秒执行一次),crontab 不支持 3. **日期和星期别一起写**!比如你写\* \* 15 \* 1,本意是「每月 15 号和每周一都执行」,但系统会理解成「每月 15 号且当天是周一才执行」,完全不符合预期 4. \*\*% 符号必须加转义符 \*\*!crontab 里 % 是特殊字符代表换行,比如date +%Y-%m-%d必须写成date +\\%Y-\\%m-\\%d 5. **别随便用 crontab -r**!这个命令会直接删掉你所有的定时任务,没有回收站!想删单个任务,用crontab -e进去删对应行就行,或者用crontab -i,删之前会让你确认,更安全 6. **命令 / 脚本必须写绝对路径**!定时任务的环境变量和你登录的环境不一样,相对路径大概率会执行失败 #### 5. 用户级任务 vs 系统级任务 * **用户级任务**:用crontab -e编辑,每个用户都能设置自己的任务,存在/var/spool/cron/用户名里,只能自己用 * **系统级任务**:只有 root 能编辑,修改/etc/crontab文件,比用户级多了一个「执行用户」字段,用来给整个系统设置任务,格式是: 分 时 日 月 周 执行用户 命令/脚本 ### 四、练习题答案拆解(每个都给你讲明白) 咱们挑几个典型的,教你怎么一步步写出来,剩下的照着逻辑套就行: 1. ### **每天凌晨 3 点半和 12 点半执行脚本** * 分钟:30 分 → 第一个字段 30 * 小时:3 点和 12 点,不连续用逗号 → 3,12 * 日 / 月 / 周:每天都执行 → 全写 \* * 最终:30 3,12 \* \* \* cmd 2. #### **每周六和周日凌晨 1 点 10 分执行命令** * 分钟:10 分 → 10 * 小时:1 点 → 1 * 日 / 月:任意 → \* * 星期:周六是 6,周日是 0 → 6,0 * 最终:10 1 \* \* 6,0 cmd 3. #### **每天 18 点到 23 点之间,每隔 30 分钟执行一次** * 分钟:每隔 30 分钟 → \*/30 * 小时:18 点到 23 点 → 18-23 * 日 / 月 / 周:每天 → \* * 最终:\*/30 18-23 \* \* \* cmd *** ** * ** *** ## 结尾总结 Linux 定时任务核心就两个工具: * 一次性任务用at,简单方便,执行完就结束 * 循环重复任务用crontab,企业里最常用,记住 6 字段语法,90% 的自动化场景都能搞定 最后再提醒一句:定时任务一定要写绝对路径,执行失败先去/var/log/cron看日志,90% 的问题都能找到原因!