Linux系统的定时任务

在这里插入图片描述

一、基本概念

1.1 前言

  每个人或多或少都有些日常琐事或者是工作,有的工作事例行性的,例如每年一次的涨薪、每月一次的工作报告、每天需要的打卡灯;有的工作则是临时发生的,例如刚好总公司有高层来访,需要你准备演讲器材等。用在生活上面,例如每年家人的生日、每天的起床时间等,还有突发性的事情等。
  像上面这些例行性工作,通常你的要记录在日历上面才能避免忘记。不过,由于我们经常在电脑前面的缘故,如果电脑能够主动通知我们的话,那么不久轻松的多了!这个时候 Linux 的例行性工作调度就可以派上用场了,在不考虑硬件与我们服务器的连接状态下,我们的Linux可以帮你提醒很多任务,例如,每天早上8:00要服务器连接上音响,并启动音乐来唤你起床;而中午12:00希望Linux可以发一封邮件到你的邮箱,提醒你可以去吃午餐了;另外,在每天家人生日的前一天,先发一封邮件提醒你,以免忘记这么重要的一天。那么Linux的例行性工作是如何进行调度的呢?
  其实大部分系统管理工作都是通过定期自动执行某个脚本来完成的,那么如果定期执行某个脚本呢?这就要借助 Linux 的 cron 这个系统服务来控制了。Linux 系统采用 crond 守护进程来控制系统和用户的计划任务,实现周期性的执行某种任务或处理某些事件。Linux系统本身就有很多的计划任务,在安装完成操作系统后,默认会安装 crond 服务工具,且 crond 服务默认就是自启动的。crond服务每分钟都会检查是否有需要执行的任务,如果有要执行的工作便会自动执行该工作。

在这里插入图片描述

1.2 简介

  在介绍 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

813 03:22:01 centos-8.4-linux.shared anacron[27719]: Job `cron.daily' terminated
813 03:22:01 centos-8.4-linux.shared anacron[27719]: Normal exit (1 job run)
813 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
813 03:24:01 centos-8.4-linux.shared anacron[23471]: Normal exit (2 jobs run)
813 04:01:01 centos-8.4-linux.shared CROND[31987]: (root) CMD (run-parts /etc/cron.hourly)
813 05:01:01 centos-8.4-linux.shared CROND[36213]: (root) CMD (run-parts /etc/cron.hourly)
813 06:01:01 centos-8.4-linux.shared CROND[40458]: (root) CMD (run-parts /etc/cron.hourly)
813 07:01:01 centos-8.4-linux.shared CROND[44738]: (root) CMD (run-parts /etc/cron.hourly)
813 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 文件时,给确认提示
filefile 为命令文件名,表示将 file 作为 crontab 的任务列表文件并载入 crontab。
如果在命令行中没有指定文件,crontab 将接受标准输入(键盘)上键入的命令

  其实 crontab 定时任务非常简单,只需执行 crontab -e 命令,然后输入想要定时执行的任务即可。不过,当执行 crontab -e 命令时,打开的是一个空文件,而且操作方法和 Vim 是一致的。当 crontab -e 编辑完成之后,一旦保存退出,那么这个定时任务实际就会写入 /var/spool/cron/ 目录中,每个用户的定时任务用自己的用户名进行区分。而且 crontab 命令只要保存就会生效,只要 crond 服务是启动的。

1.3 任务分类

linux 任务调度的工作主要分为以下两类:

  • 1、系统执行的工作:系统周期性所要执行的工作,如备份系统数据、清理缓存等。在/etc/目录下有一个crontab文件,这个就是系统任务调度的配置文件。
  • 2、个人执行的工作:某个用户定期要做的工作,比如定时更新同步数据、重要数据备份、定时邮件提醒等。用户可以使用 crontab 工具来定制自己的计划任务。

二、系统任务调度

2.1 简介

  系统计划任务一般儿是执行系统级别的周期性任务,例如系统备份、把缓存数据写入硬盘、清理日志文件等。系统计划任务在 /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 改成自己的账号,好随时了解系统的状况!

2.2 crontab设置

   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 服务是运行的,否则无法执行。

三、用户任务调度

3.1 简介

  Linux的每个用户可以定义自己的计划任务,周期性的执行脚本或程序。默认情况下,任务用户只要不被列入 /etc/cron.deny文件当中,那么就可以直接执行 crontab -e去编辑自己的计划任务。计划任务的内容存放在crontab文件中,每个用户都有自己的crontab文件,一般位于 /var/spool/cron 目录下。当用户增加定时任务时,会在该目录中添加以自己名称命名的文件,并将定时任务保存在其中。执行 crontab -e后会进入 vi 的编辑界面,然后以一个工作一行来编辑,编辑完成之后在输入 :wq保存离开 vi就可以了。而每项工作(每行)的格式都是具有六个字段,这六个字段的意义如下表所示:

代表意义分钟小时日期月份命令
数字范围1~590~231~311~120~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**。

3.2 crontab设置

cron 最难的部分就是设置定时任务执行时间,时间格式如下:

t1 t2 t3 t4 t5 program
  • 其中 t1 是表示分钟,t2 表示小时,t3 表示一个月份中的第几日,t4 表示月份,t5 表示一个星期中的第几天。program 表示要执行的程序。
  • 当 t1 为 * 时表示每分钟都要执行 program,t2 为 * 时表示每小时都要执行程序,其余类推
  • 当 t1 为 a-b 时表示从第 a 分钟到第 b 分钟这段时间内要执行,t2 为 a-b 时表示从第 a 到第 b 小时都要执行,其余类推
  • 当 t1 为 */n 时表示每 n 分钟个时间间隔执行一次,t2 为 */n 表示每 n 小时个时间间隔执行一次,其余类推
  • 当 t1 为 a, b, c,… 时表示第 a, b, c,… 分钟要执行,t2 为 a, b, c,… 时表示第 a, b, c…个小时要执行,其余类推
    在这里插入图片描述

三、停机期间的任务调度

3.1 前言

  如果你的 Linux 主机是作为24小时全天、全年无休的服务器之用,那么只要有 crond 服务来管理定时任务调度即可。但如果你的服务器并非24小时无间断开机,那么该如何进行例行性任务(工作)呢?举例来说,如果每天晚上都要关机,等到白天才会启动 Linux 主机,但是设定的定时任务大多在每天凌晨4点进行,而在这个时间点,服务器又处于关机状态,如此一来不就导致系统很多定时任务无法运行,那可怎么办?此时这就的要 anacron 工具了。

3.2 什么是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 119 2019 /etc/cron.hourly/0anacron

3.3 anacrontab 文件

  在当前的 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 的执行过程。如下所示:

  1. 有 /etc/anacrontab 分析到 cron.daily 这项任务的天数为1天,读取 /var/spool/anacron/cron.daily 文件中 anacron 上一次执行的时间戳。
  2. 上一次执行的时间戳和当前时间比较,如果两个时间的差值超过 1 天,就执行 cron.daily 工作,而且只能在 03:00-22:00 执行这个工作。
  3. 执行工作时强制延迟时间为 5 分钟,再随机延迟 0~45 分钟。
  4. 使用 nice 命令指定默认优先级,延迟时间过后,使用 run-parts 脚本执行 /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

3.4 小结

  大现在知道为什么隔了一阵子才将 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记录系统操作的日志,例如:用户登录

注意事项

  • 系统任务调度我们可以通过/etc/crontab文件直接配置,用户定时任务调度我们一般通过 crontab –e 命令来进行配置,可以说 /etc/crontab 里的任务是系统的计划任务
  • 每次编辑完某个用户的 cron 设置后,cron 自动在 /var/spool/cron 下生成一个与此用户同名的文件,此用户的 cron 信息都记录在这个文件中,该文件是不支持直接编辑的,只可以用 crontab -e 来编辑
  • crontab 中的 command 尽量使用绝对路径,否则会经常因为路径错误导致任务无法执行。
  • 新创建的 cron 任务,不会马上执行,至少要过 2 分钟后才可以
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独泪了无痕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值