赞
踩
每个人或多或少都有些日常琐事或者是工作,有的工作事例行性的,例如每年一次的涨薪、每月一次的工作报告、每天需要的打卡灯;有的工作则是临时发生的,例如刚好总公司有高层来访,需要你准备演讲器材等。用在生活上面,例如每年家人的生日、每天的起床时间等,还有突发性的事情等。
像上面这些例行性工作,通常你的要记录在日历上面才能避免忘记。不过,由于我们经常在电脑前面的缘故,如果电脑能够主动通知我们的话,那么不久轻松的多了!这个时候 Linux 的例行性工作调度就可以派上用场了,在不考虑硬件与我们服务器的连接状态下,我们的Linux可以帮你提醒很多任务,例如,每天早上8:00要服务器连接上音响,并启动音乐来唤你起床;而中午12:00希望Linux可以发一封邮件到你的邮箱,提醒你可以去吃午餐了;另外,在每天家人生日的前一天,先发一封邮件提醒你,以免忘记这么重要的一天。那么Linux的例行性工作是如何进行调度的呢?
其实大部分系统管理工作都是通过定期自动执行某个脚本来完成的,那么如果定期执行某个脚本呢?这就要借助 Linux 的 cron 这个系统服务来控制了。Linux 系统采用 crond 守护进程来控制系统和用户的计划任务,实现周期性的执行某种任务或处理某些事件。Linux系统本身就有很多的计划任务,在安装完成操作系统后,默认会安装 crond 服务工具,且 crond 服务默认就是自启动的。crond服务每分钟都会检查是否有需要执行的任务,如果有要执行的工作便会自动执行该工作。
在介绍 crontab 命令之前,首先要介绍一下 crond,因为 crontab 命令需要 crond 服务支持。crond 是 Linux 下用来周期地执行某种任务或等待处理某些事件的一个守护进程,和 Windows 中的计划任务有些类似。执行以下命令可以看到crond服务的运行情况:
[root@centos-8 ~]# systemctl status crond
● crond.service - Command Scheduler
Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2022-08-13 00:01:03 CST; 8h ago
Main PID: 1063 (crond)
Tasks: 1 (limit: 23496)
Memory: 7.9M
CGroup: /system.slice/crond.service
└─1063 /usr/sbin/crond -n
8月 13 03:22:01 centos-8.4-linux.shared anacron[27719]: Job `cron.daily' terminated
8月 13 03:22:01 centos-8.4-linux.shared anacron[27719]: Normal exit (1 job run)
8月 13 03:24:01 centos-8.4-linux.shared anacron[23471]: Job `cron.monthly' started
8月 13 03:24:01 centos-8.4-linux.shared anacron[23471]: Job `cron.monthly' terminated
8月 13 03:24:01 centos-8.4-linux.shared anacron[23471]: Normal exit (2 jobs run)
8月 13 04:01:01 centos-8.4-linux.shared CROND[31987]: (root) CMD (run-parts /etc/cron.hourly)
8月 13 05:01:01 centos-8.4-linux.shared CROND[36213]: (root) CMD (run-parts /etc/cron.hourly)
8月 13 06:01:01 centos-8.4-linux.shared CROND[40458]: (root) CMD (run-parts /etc/cron.hourly)
8月 13 07:01:01 centos-8.4-linux.shared CROND[44738]: (root) CMD (run-parts /etc/cron.hourly)
8月 13 08:01:01 centos-8.4-linux.shared CROND[48933]: (root) CMD (run-parts /etc/cron.hourly)
接下来,在介绍 crontab 命令。Linux 是通过 /etc/cron.allow 和 /etc/cron.deny 文件来限制某些用户是否可以使用 crontab 命令的。 当系统中有 /etc/cron.allow 文件时,只有写入此文件的用户可以使用 crontab 命令,没有写入的用户不能使用 crontab 命令。同样,如果有此文件,/etc/cron.deny 文件会被忽略,因为 /etc/cron.allow 文件的优先级更高。当系统中只有 /etc/cron.deny 文件时,写入此文件的用户不能使用 crontab 命令,没有写入文件的用户可以使用 crontab 命令。crontab 命令的基本格式如下:
crontab [选项] [file]
crontab 是用来让使用者在固定时间或固定间隔执行程序之用,换句话说,也就是类似使用者的时程表,其常用的选项有几下几个:
选项 | 说明 |
---|---|
-u user | 用来设定某个用户的 crontab 服务,不加 -u 则为当前用户,此选项一般有 root 用户来运行。 |
-e | 编辑某个用户的 crontab 文件内容。如果不指定用户,则表示编辑当前用户的 |
-l | 显示某用户的 crontab 文件内容,如果不指定用户,则表示显示当前用户 |
-r | 删除某用户的 crontab 文件,如果不指定用户,则默认删除当前用户 |
-i | 在删除用户的 crontab 文件时,给确认提示 |
file | file 为命令文件名,表示将 file 作为 crontab 的任务列表文件并载入 crontab。 如果在命令行中没有指定文件,crontab 将接受标准输入(键盘)上键入的命令 |
其实 crontab 定时任务非常简单,只需执行 crontab -e
命令,然后输入想要定时执行的任务即可。不过,当执行 crontab -e
命令时,打开的是一个空文件,而且操作方法和 Vim 是一致的。当 crontab -e
编辑完成之后,一旦保存退出,那么这个定时任务实际就会写入 /var/spool/cron/ 目录中,每个用户的定时任务用自己的用户名进行区分。而且 crontab 命令只要保存就会生效,只要 crond 服务是启动的。
linux 任务调度的工作主要分为以下两类:
系统计划任务一般儿是执行系统级别的周期性任务,例如系统备份、把缓存数据写入硬盘、清理日志文件等。系统计划任务在 /etc/crontab 文件配置,下图展示了文件的内容,在该文件中,可以设置环境变量,可以指定执行任务的用户。
crontab文件中的每个任务由执行时间和执行命令两部分组成的:
执行时间有五个参数,即上图中数字1~5,每一行都代表一项任务,每行的每个字段代表一项设置,如下表所示:
数字 | 含义 | 范围 |
---|---|---|
1⃣️ | 一小时当中的第几分钟(minute) | 从0到59之间的任何整数 |
2⃣️ | 一天当中的第几小时(hour) | 从0到23之间的任何整数 |
3⃣️ | 一个月当中的第几天(day) | 从1到31之间的任何整数 |
4⃣️ | 一年当中的第几个月(month) | 从1到12之间的任何整数 |
5⃣️ | 一周当中的星期几(week) | 是从0到7之间的任何整数,这里的0或7代表星期日 |
执行命令也就是任务执行的程序,可以是shell脚本,也可以是其它的可执行文件。
命令 | 说明 |
---|---|
command | 要执行的命令,可以是系统命令,也可以是自己编写的脚本文件 |
还有一点儿要特别注意,就是 /etc/crontab 文件中的 MAILTO=root选项。当 /etc/crontab 文件中的例行性任务的命令发生错误时,或者是该任务的执行结果有 STDOUT或者STDERR时,就会将错误信息或者屏幕显示的信息发送给谁,默认当前是由系统直接寄发一份邮件给 root。不过,由于root并无法在客户端中以 POP3 之类的软件收信,因此,建议将这 Email 改成自己的账号,好随时了解系统的状况!
crontab -e
是每个用户都可以执行的命令,也就是说,不同的用户身份可以执行自己的定时任务。但是有些定时任务需要系统执行,这时就需要编辑 /etc/crontab 文件了。当然,并不是说写入 crontab 配置文件中的定时任务在执行时不需要用户身份,而是 crontab -e
命令在定义定时任务时,默认用户身份是当前登录用户。而在修改 /etc/crontab 配置文件时,定时任务的执行者身份是可以手工指定的。这样定时任务的执行会更加灵活,修改起来也更加方便。
其实,对普通用户来讲,并不需要知道这个定时任务到底是由哪个程序调用的,只需要知道是如何使用系统的 crontab 设置,而配置系统的crontab文件方法都有两种,具体看个人的习惯。
第一种方法就是把需要定时执行的工作写成脚本程序,并赋予执行权限,然后直接把这个脚本复制到 /etc/cron.hourly、/etc/cron.daily、/etc/cron.weekly、/etc/cron.monthly目录中的任意一个。比如,我需要让某个脚本每周执行,就把这个脚本复制到 /etc/cron.weekly/ 目录中。这样这个脚本就会每周执行一次。
第二种方法就是修改 /etc/crontab 这个配置文件,加入自己的定时任务,不过需要注意指定脚本的执行者身份。例如:
# 1、建立 /root/cron/ 目录
[root@localhost ~]# mkdir cron
# 2、在/root/cron/hello.log文件中写入“hello”
[root@localhost cron]# vim /root/cron/hello.sh
#/bin/bash
echo "hello" >> /root/cron/hello.log
# 3、赋予执行权限。
[root@localhost cron]# chmod 755 hello.sh
基本上,cron 服务的最低检测限制是"分钟",所有 cron 会每分钟去读一次 /etc/crontab 与 /var/spool/cron里面的数据内容,因此,只要保存 /etc/crontab 文件,这个定时任务就可以执行了。再上面的示例中,由于hello.sh脚本放入了/root/cron/目录中,所以每分钟执行一次。
定时任务能够执行的前提条件,就是要确定 crond 服务是运行的,否则无法执行。
Linux的每个用户可以定义自己的计划任务,周期性的执行脚本或程序。默认情况下,任务用户只要不被列入 /etc/cron.deny文件当中,那么就可以直接执行 crontab -e
去编辑自己的计划任务。计划任务的内容存放在crontab文件中,每个用户都有自己的crontab文件,一般位于 /var/spool/cron 目录下。当用户增加定时任务时,会在该目录中添加以自己名称命名的文件,并将定时任务保存在其中。执行 crontab -e
后会进入 vi 的编辑界面,然后以一个工作一行来编辑,编辑完成之后在输入 :wq
保存离开 vi就可以了。而每项工作(每行)的格式都是具有六个字段,这六个字段的意义如下表所示:
代表意义 | 分钟 | 小时 | 日期 | 月份 | 周 | 命令 |
---|---|---|---|---|---|---|
数字范围 | 1~59 | 0~23 | 1~31 | 1~12 | 0~7 | 执行的任务 |
另外,还有一些辅助的字符,大概有下面这些,如下表所示:
特殊符号 | 含义 |
---|---|
星号(*) | 代表任何时间,只要其他值满足都执行。比如第一个 * 就代表一小时种每分钟都执行一次的意思 |
逗号(,) | 用逗号隔开的值指定一个列表范围,例如:1,2,5,7,8,9 |
中杠(-) | 代表一段时间范围内。比如 0 5 * * 1-6 命令 ,代表在周一到周六的凌晨 5 点 0 分执行命令 |
正斜线(/) | 代表每隔多久执行一次。比如*/10 * * * * 命令 ,代表每隔 10 分钟就执行一次命令 |
现在我们已经对这几个时间字段非常熟悉了,可是在“执行的任务”字段中都可以写什么呢?既可以定时执行系统命令,也可以定时执行某个 Shell 脚本,这里举几个实际的例子。
让系统每隔 5 分钟就向 /tmp/test 文件中写入一行“11”,验证一下系统定时任务是否会执行
[root@centos-linux-8 etc ~]# crontab -e
#进入编辑界面
*/5 * * * * /bin/echo "11" >> /tmp/test
这个任务在时间工作中没有任何意义,但是可以很简单地验证我们的定时任务是否可以正常执行。
在每月 1 日、10 日、15 日的凌晨 3 点 30 分都定时执行日志备份脚本 autobak.sh
[root@localhost ~]# crontab -e
30.3 1,10,15 * * /root/sh/autobak.sh
这些定时任务保存之后,就可以在指定的时间执行了。我们可以使用命令来查看和删除定时任务,命令如下:
# 查看root用户的crontab任务
[root@centos-linux-8 ~]# crontab -l
*/5 * * * * /bin/echo "11" >> /tmp/test
30.3 1,10,15 * * /root/sh/autobak.sh
# 删除root用户所有的定时任务。如果只想删除某个定时任务,则可以执行“crontab -e”命令进入编辑模式手工删除
root@centos-linux-8 ~]# crontab -r
如果用命令
crontab -r
就会删除当前用户的crontab文件,例如切换到oracle账号下,执行了该命令,那么 /var/spool/cron/oracle 文件就会删除,如果要创建该文件只需要用crontab -e命令即可。注意,普通用户一般没有权限访问**/var/spool/cron**。
cron 最难的部分就是设置定时任务执行时间,时间格式如下:
t1 t2 t3 t4 t5 program
如果你的 Linux 主机是作为24小时全天、全年无休的服务器之用,那么只要有 crond 服务来管理定时任务调度即可。但如果你的服务器并非24小时无间断开机,那么该如何进行例行性任务(工作)呢?举例来说,如果每天晚上都要关机,等到白天才会启动 Linux 主机,但是设定的定时任务大多在每天凌晨4点进行,而在这个时间点,服务器又处于关机状态,如此一来不就导致系统很多定时任务无法运行,那可怎么办?此时这就的要 anacron 工具了。
anacron 并不是用来替代 crontab 的,anacron 存在的目的就在于上面提到的,在处理非24小时一直启动的 Linux 系统的 crontab 的执行。所有 anacron 并不能指定何时执行某项任务,而是以天为单位或者是在开机后立即执行 anacron 的操作,它会去检测停机期间内应该执行但是并没有执行的 crontab 任务,并将该任务执行一遍,然后 anacron 就会自动停止了。
由于 anacron 会以 1 天、1周、一个月作为检测周期去检测系统未进行的 crontab 任务,因此对于某些特殊的使用环境非常有帮助,举例来说,我们需要在凌晨5点执行系统的日志备份,但 Linux 服务器不是 24 小时开机的,在晚上需要关机,白天上班之后才会再次开机。在这个定时任务的执行时间内服务器刚好没有开机,那么这个定时任务就不会执行了,anacron 刚好可以解决这个问题,如果有这样的任务,那么 anacron 会在特定的时间重新执行这些定时任务。
那么,anacron 是如何判断系统什么时候关机而某些定时任务已经超过执行时间的呢?这就需要借助 anacron 读取的时间记录文件。anacron 会分析现在的时间与时间记录文件所记载的上次执行 anacron 的时间,将两者进行比较,如果两个时间的差值超过 anacron 的指定时间差值(一般是 1 天、7 天和一个月),就说明有定时任务没有执行,这时 anacron 会介入并执行这个漏掉的定时任务。所以 anacron 其实也是通过 crontab 来运行的!因此 anacron 运行的时间通常有两个,一个是系统开机期间运行,一个是写入 crontab 的调度中,从而保证在关机时没有执行的定时任务不会被漏掉。
在 CentOS 中,anacron 不再是单独的服务,而变成了系统命令。基本上,anacron 命令的基本格式如下,下表罗列出了此命令常用的几个选项及各自的功能。
anacron [选项] [工作名]
选项 | 功能 |
---|---|
-f | 强制执行相关工作,忽略时间戳。 |
-u | 更新 /var/spool/anacron/cron.{daily,weekly,monthly} 文件中的时间戳为当前日期,但不执行任何工作。 |
-s | 依据 /etc/anacrontab 文件中设定的延迟时间顺序执行工作,在前一个工作未完成前,不会开始下一个工作。 |
-n | 立即执行 /etc/anacrontab 中所有的工作,忽略所有的延迟时间。 |
工作名 | 依据 /etc/anacrontab 文件中定义的工作名 |
我们来追踪查看下 anacron,如下所示:
[root@centos-linux-8 ~]# ll /etc/cron*/*ana*
-rwxr-xr-x. 1 root root 575 11月 9 2019 /etc/cron.hourly/0anacron
在当前的 Linux 中,其实不需要执行任何 anacron 命令,只需要配置好 /etc/anacrontab 文件,系统就会依赖这个文件中的设定来通过 anacron 执行定时任务了。那么,关键就是 /etc/anacrontab 文件的内容了。这个文件的内容如下:
[root@centos-linux-8 ~]# vi /etc/anacrontab
# /etc/anacrontab: configuration file for anacron
# See anacron(8) and anacrontab(5) for details.
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# 最大随机廷迟
RANDOM_DELAY=45
# fanacron的执行时间范围是3:00~22:00
START_HOURS_RANGE=3-22
#period in days delay in minutes job-identifier command
# 每天开机 5 分钟后就检查 /etc/cron.daily 目录内的文件是否被执行,如果今天没有被执行,那就执行
1 5 cron.daily nice run-parts /etc/cron.daily
# 每隔 7 天开机后 25 分钟检查 /etc/cron.weekly 目录内的文件是否被执行,如果一周内没有被执行,就会执行
7 25 cron.weekly nice run-parts /etc/cron.weekly
# 每隔一个月开机后 45 分钟检查 /etc/cron.monthly 目录内的文件是否被执行,如果一个月内没有被执行,那就执行
@monthly 45 cron.monthly nice run-parts /etc/cron.monthly
在这个文件中,"RANDOM_DELAY"定义的是最大随机延迟,也就是说,任务如果超过时间没有执行,并不会马上执行,而是先延迟强制延迟时间,再延迟随机延迟时间,之后再执行。“START_HOURS_RANGE” 是定义 anacron 执行时间范围,anacron 只会在这个时间范围内执行。
由于 /etc/ cron.daily 内的任务会比较多,因此我们用每天进行的任务来说明一下 anacron 的执行过程。如下所示:
大家会发现,/etc/cron.{daily,weekly,monthly} 目录中的脚本在当前的 Linux 中是被 anacron 调用的,不再依靠 cron 服务。不过,anacron 不用设置多余的配置,我们只需要把需要定时执行的脚本放入 /etc/cron.{daily,weekly,monthly} 目录中,就会每天、每周或每月执行,而且也不再需要启动 anacron 服务了。如果需要进行修改,则只需修改 /etc/anacrontab 配置文件即可。
比如,我让定时任务在凌晨 03:00-05:00 执行,就可以进行如下修改:
[root@centos-linux-8 ~]# vi /etc/anacrontab
# /etc/anacrontab: configuration file for anacron
# See anacron(8) and anacrontab(5) for details.
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# 把最大随机廷迟改为0分钟,不再随机廷迟
RANDOM_DELAY=0
# 执行时间范围为03:00—05:000
START_HOURS_RANGE=3-5
# 把强制延迟也改为0分钟,不再强制廷迟
#period in days delay in minutes job-identifier command
1 0 cron.daily nice run-parts /etc/cron.daily
7 0 cron.weekly nice run-parts /etc/cron.weekly
大现在知道为什么隔了一阵子才将 CentOS 开机,开机过后约1小时左右系统会有一小段时间的忙碌,而且硬盘还会跑个不停了吧!那是因为 anacron 正在执行过去 crontab 未进行的各项任务调度。
如果我们使用 crontab 来定时执行脚本,无法执行,但是如果直接通过命令又可以正常执行,这主要是因为无法读取环境变量的原因。解决方法:
所有命令需要写成绝对路径形式,如: /usr/local/bin/docker。
在 shell 脚本开头使用以下代码
!/bin/sh
. /etc/profile
. ~/.bash_profile
在 /etc/crontab 中添加环境变量,在可执行命令之前添加命令 . /etc/profile;/bin/sh,使得环境变量生效,例如:
20 03 * * * . /etc/profile;/bin/sh /tmp/test.sh
当定时任务调度(执行)出现错误的时候,需要排查错误,除了尝试 /etc/init.d/crond restart
解决问题外,还可以到定时任务日志文件中去查询错误的原因。
路径 | 说明 |
---|---|
/var/log/cron* | cron 开头的文件,里面包含了crontab的执行记录,可以查看到执行那些定时任务 |
/var/log/messages | 记录系统操作的日志,例如:用户登录 |
crontab –e
命令来进行配置,可以说 /etc/crontab
里的任务是系统的计划任务。Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。