linux-定时任务

定时任务

在linux中定时任务分为单次任务和循环多次任务,单次任务为任务执行一次就结束了,多次循环为任务会根据我提前设置好的时间循环多次执行,直到我们取消定时任务为止,在实际工作中多次循环使用的频率相比与单词执行的频率会高一些,比如日志备份,要求每天凌晨一点要执行,数据库文件备份要求每天定期进行备份,这些场景都会使用到定时任务功能,也刻印大大减轻系统管理者的难度。

1、at:单次执行

要想使用 at 命令,读者需提前安装好 at 软件包,并开启 atd 服务。因此,首先来看看如何安装 at 软件包。

在 Linux 系统中,查看 at 软件包是否已安装,可以使用 rpm -q 命令,如下所示:

[root@localhost ~]# rpm -q at
package at is not installed

可以看到,当前系统未安装 at 软件包,可使用如下命令进行安装:

[root@localhost ~]# yum -y install at

开启at服务并加入开机自启动

[root@localhost ~]# systemctl enable --now atd

安装好 at 软件包并开启 atd 服务之后,at 命令才可以正常使用,不过在此之前,我们还要学习一下 at 命令的访问控制。

访问控制指的是允许哪些用户使用 at 命令设定定时任务,或者不允许哪些用户使用 at 命令。大家可以将其想象成设定黑名单或白名单,这样更容易理解。

at 命令的访问控制是依靠 /etc/at.allow(白名单)和 /etc/at.deny(黑名单)这两个文件来实现的,具体规则如下:

1)如果系统中有 /etc/at.allow 文件,那么只有写入 /etc/at.allow 文件(白名单)中的用户可以使用 at 命令,其他用户不能使用 at 命令(注意,/etc/at.allow 文件的优先级更高,也就是说,如果同一个用户既写入 /etc/at.allow 文件,又写入 /etc/at.deny 文件,那么这个用户是可以使用 at 命令的)。

2) 如果系统中没有 /etc/at.allow 文件,只有 /etc/at.deny 文件,那么写入 /etc/at.deny 文件(黑名单)中的用户不能使用 at 命令,其他用户可以使用 at 命令。不过这个文件对 root 用户不生效。

3)如果系统中这两个文件都不存在,那么只有 root 用户可以使用 at 命令。

系统中默认只有 /etc/at.deny 文件,而且这个文件是空的,因此,系统中所有的用户都可以使用 at 命令。不过,如果我们打算控制用户的 at 命令权限,那么只需把用户写入 /etc/at.deny 文件即可。

对于 /etc/at.allow 和 /etc/at.deny 文件的优先级,我们做一个实验来验证一下,命令如下:

系统中默认只有at.deny文件

[root@localhost ~]# echo user1 >> /etc/at.deny
[root@localhost ~]# cat /etc/at.deny
user1

把user1用户写入/etc/at.deny文件

[root@localhost ~]# su - user1
[user1@localhost ~]$ at 04:00
You do not have permission to use at.

没有权限使用at命令,切换成user1用户,这个用户已经不能执行at命令了

[user1@localhost ~]$ exit
logout

返回root身份

[root@localhost ~]# echo user1 >> /etc/at.allow
[root@localhost ~]# cat /etc/at.allow
user1

建立/etc/at.allow文件,并在文件中写入user1用户

[root@localhost ~]# su - user1
[user1@localhost ~]$ at 04:00
at>

切换成user1用户,user1用户可以执行at命令。这时user1用户既在/etc/at.deny文件中,又在/etc/at.allow文件中,是/etc/at.allow文件的优先级更高

[user1@localhost ~]$ exit
logout

返回root身份

[root@localhost ~]# at 04:00
at>
#root用户虽然不在/etc/at.allow文件中,但是也能执行at命令

#说明root用户不受这两个文件的控制

这个实验说明了 /etc/at.allow 文件的优先级更高,如果 /etc/at.allow 文件存在,则 /etc/at.deny 文件失效。/etc/at.allow 文件的管理更加严格,因为只有写入这个文件的用户才能使用 at 命令,如果需要禁用 at 命令的用户较多,则可以把少数用户写入这个文件。/etc/at.deny 文件的管理较为松散,如果允许使用 at 命令的用户较多,则可以把禁用的用户写入这个文件。不过这两个文件都不能对 root 用户生效。

接下来正式介绍 at 命令。at 命令的格式非常简单,语法格式

[root@localhost ~] # at [选项] [时间]

有关此命令常用的几个选项及各自含义如表 1 所示。

在这里插入图片描述

表 2 罗列了此命令中关于时间参数可用的以下格式

在这里插入图片描述

at 命令只要指定正确的时间,就可以输入需要在指定时间执行的命令。这个命令可以是系统命令,也可以是 Shell 脚本

范例1:

[user1@localhost ~]$ at 20:18       ##运行脚本
at> /home/user1/hello.sh >>/home/user1/log
at> <EOT>
job 3 at Sun Oct 03 20:18:00 2021
[user1@localhost ~]$ date
Sun Oct 03 20:18:08 CST 2021
[user1@localhost ~]$ ls
hello.sh  log
[user1@localhost ~]$ vim log 
[user1@localhost ~]$ ls
hello.sh  log
[user1@localhost ~]$ 

[user1@ali01 root]$ at now +10 minutes    ##10分钟后执行
at> echo test >/tmp/test.txt
at> <EOT>
Sun Oct 03 21:18:08 CST 2021

上述定时任务的意思是,在20:18分执行hello.sh的这个脚本,并将输出的日志追加到log这个文件中,定时任务使用ctrl +D保存

查看定时任务

at -c 5   #查看第5个任务
LOGNAME=user1; export LOGNAME
LESSOPEN=\|\|/usr/bin/lesspipe.sh\ %s; export LESSOPEN
OLDPWD=/home/user1; export OLDPWD
cd /home/user1 || {
	 echo 'Execution directory inaccessible' >&2
	 exit 1
}
${SHELL:-/bin/sh} << 'marcinDELIMITER1f7df460'
/home/user1/hello.sh >>/log1                        ##定时任务

marcinDELIMITER1f7df460

在使用系统定时任务时,不论执行的是系统命令还是 Shell 脚本,最好使用绝对路径来写命令,这样不容易报错。at 任务一旦使用 Ctrl+D 快捷键保存,实际上写入了 /var/spool/at/ 这个目录,这个目录内的文件可以直接被 atd 服务调用和执行。

atq 命令用于查看当前等待运行的工作,atrm 命令后者用于删除指定的工作

查看当前等待运行的工作任务

atq
[user1@localhost ~]$ atq
6	Sun Oct 03 20:30:00 2021 a user1

删除当前等待运行的任务

[user1@localhost ~]$ atrm 6
[user1@localhost ~]$ atq      #再查看就没有了。

at的参考案例

案例1:三天后的下午5点执行/bin/ls 

[user1@localhost ~]$ at 5pm+3 days
at> /bin/ls /<EOT>
job 1 at Fri Jun 14 17:00:00 2021

案例2:明天17点钟,输出时间到指定文件内
[user1@localhost ~]$at 17:00 tomorrow
at> date > /root/date.log
at> <EOT>
job 2 at Wed Jun 12 17:00:00 2021


案例3:一分钟后执行/tmp/date文件中的内容
[user1@localhost ~]$ cat /tmp/date        #查看/tmp/date文件中内容
#!/bin/bash
date "+%F %T" > /root/date.log

[root@vms002 /]# at -f /tmp/date now +1 minutes   #设置1分钟后执行/tmp/date文件中的内容
job 4 at Tue Jun 11 15:47:00 2021
2、crontab:循环多次执行

前面学习了 at 命令,此命令在指定的时间仅能执行一次任务,但在实际工作中,系统的定时任务一般是需要重复执行的。而 at 命令显然无法满足需求,这是就需要使用 crontab 命令来执行循环定时任务。

在介绍 crontab 命令之前,我们首先要介绍一下 crond,因为 crontab 命令需要 crond 服务支持。crond 是 Linux 下用来周期地执行某种任务或等待处理某些事件的一个守护进程,和 Windows 中的计划任务有些类似。

2.1 安装完操作系统后,默认会安装crond的服务

[root@localhost at]# systemctl status crond
● crond.service - Command Scheduler
   Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
   Active: active (running) since Sun 2021-10-10 19:50:45 CST; 40min ago
 Main PID: 883 (crond)
   CGroup: /system.slice/crond.service
           └─883 /usr/sbin/crond -n

Oct 10 19:50:45 localhost.localdomain systemd[1]: Started Command Scheduler.
Oct 10 19:50:45 localhost.localdomain crond[883]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 0% if used.)
Oct 10 19:50:45 localhost.localdomain crond[883]: (CRON) INFO (running with inotify support)

其实,在安装完成操作系统后,默认会安装 crond 服务工具,且 crond 服务默认就是自启动的。crond 进程每分钟会定期检查是否有要执行的任务,如果有,则会自动执行该任务。

接下来,在介绍 crontab 命令。该命令和 at 命令类似,也是通过 /etc/cron.allow 和 /etc/cron.deny 文件来限制某些用户是否可以使用 crontab 命令的。而且原则也非常相似:

1) 当系统中有 /etc/cron.allow 文件时,只有写入此文件的用户可以使用 crontab 命令,没有写入的用户不能使用 crontab 命令。同样,如果有此文件,/etc/cron.deny 文件会被忽略,因为 /etc/cron.allow 文件的优先级更高。

2) 当系统中只有 /etc/cron.deny 文件时,写入此文件的用户不能使用 crontab 命令,没有写入文件的用户可以使用 crontab 命令。

3) 这个规则基本和 at 命令的规则一致,同样是 /etc/cron.allow 文件比 /etc/cron.deny 文件的优先级高,Linux 系统中默认只有 /etc/cron.deny文件。

每个用户都可以实现自己的 crontab 定时任务,只需使用这个用户身份执行“crontab -e”命令即可。当然,这个用户不能写入 /etc/cron.deny 文件。

2.2 crontab 命令的基本格式如下:

[root@localhost ~]# crontab [选项] [file]

注意,这里的 file 指的是命令文件的名字,表示将 file 作为 crontab 的任务列表文件并载入 crontab,若在命令行中未指定文件名,则此命令将接受标准输入(键盘)上键入的命令,并将它们键入 crontab。

与此同时,表 1 罗列出了此命令常用的选项及功能。
在这里插入图片描述

接下来,我们开始学习使用crontab,编写一个crontab任务

语法:

crontab -e
#进入 crontab 编辑界面。会打开Vim编辑你的任务
* * * * * 执行的任务

这个文件中是通过 5 个“”来确定命令或任务的执行时间的,这 5 个“”的

具体含义如表 2 所示。
在这里插入图片描述

在时间表示中,还有一些特殊符号需要学习

在这里插入图片描述

当“crontab -e”编辑完成之后,一旦保存退出,那么这个定时任务实际就会写入 /var/spool/cron/ 目录中,每个用户的定时任务用自己的用户名进行区分。而且 crontab 命令只要保存就会生效

举例说明:

时间含义
30 12 * * * 命令代表在每天的12点30分执行命令
0 22 * * 2 命令代表在每周2的22点执行命令
*/5 * * * * 命令代表每过5分钟执行一次命令
40 4 * * 1-5 命令代表在每周一到周五的凌晨 4 点 40 分执行命令
0 0 1,15 * 1 命令代表每个月的1号,15号或者周1都会执行,但是不建议这样写,以免混淆

2.3 系统crontab配置文件

“crontab -e”是每个用户执行的命令,也就是说不同的用户身份可以执行自己定义的定时任务,但是有一些定时任务需要系统执行,这时就需要编辑/etc/crontab这个配置文件了。当然,并不是说写入/etc/crontab配置文件中的定时任务在执行的时候不需要用户身份,而是"cronta -e"命令定义定时任务时,默认执行的是当前登录用户,而修改/etc/crontab配置文件时,定时任务的身份是可以手动指定的,这种方式更加灵活,修改也更加方便,我们看下/etc/crontab这个文件


SHELL=/bin/bash
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 *   *  *  * user1 echo user1 >/home/user1/user.txt  #通过user1用户每分钟执行一次命令

2.4 接下来,我们实际来写几个例子感受一下

范例1:让系统每隔 1 分钟就向 /tmp/test 文件中写入一行“11”,验证一下系统定时任务是否会执行

[root@localhost ~]#crontab -e
*/1 * * * * /bin/echo "11" >/tmp/test                                  
[root@localhost at]# cd /tmp/
[root@localhost tmp]# ls
test                       
[root@localhost tmp]# cat test
11

范例2:让系统在每周日的凌晨 4 点 05 分重启一次。

[root@localhost ~]# crontab -e
05 04 * * 7 /sbin/shutdown -r now

范例3:让系统每天早上8点和晚上8点备份一下数据库文件

[root@localhost ~]# crontab -e
0 8,20 * * * /usr/mysql/bin/mysqldump -u root -h host -p dbname > backdb.sql

2.5 查看定时任务

[root@localhost tmp]# crontab -l
*/1 * * * * /bin/echo "11" >/tmp/test
05 04 * * 7 /sbin/shutdown -r now
0 8,20 * * * /usr/mysql/bin/mysqldump -u root -h host -p dbname > backdb.sql

如果删除定时任务,先使用crontab -e进入,手工删除定时任务

在书写 crontab 定时任务时,需要注意以下几个事项:

1) 6 个选项都不能为空,必须填写。如果不确定,则使用“*”代表任意时间。
2) crontab 定时任务的最小有效时间是分钟,最大有效时间是月。像 2021 年某时执行、3 点 30 分 30 秒这样的时间都不能被识别。
3) 在定义时间时,日期和星期最好不要在一条定时任务中出现,因为它们都以天为单位,非常容易让管理员混淆。
4) 在定时任务中,不管是直接写命令,还是在脚本中写命令,最好都使用绝对路径。有时使用相对路径的命令会报错。
3、 anacron

anacron 是用来做什么的呢?设想这样一个场景,Linux 服务器会在周末关机两天,但是设定的定时任务大多在周日早上进行,但在这个时间点,服务器又处于关机状态,导致系统很多定时任务无法运行。

又比如,我们需要在凌晨 5 点 05 分执行系统的日志备份,但 Linux 服务器不是 24 小时开机的,在晚上需要关机,白天上班之后才会再次开机,在这个定时任务的执行时间我们的服务器刚好没有开机,那么这个定时任务就不会执行了。anacron 就是用来解决这个问题的。

anacron 会以 1 天、1周(7天)、一个月作为检测周期,判断是否有定时任务在关机之后没有执行。如果有这样的任务,那么 anacron 会在特定的时间重新执行这些定时任务。

在这里插入图片描述

那么,anacron 是如何判断这些定时任务已经超过执行时间的呢?这就需要借助 anacron 读取的时间记录文件。anacron 会分析现在的时间与时间记录文件所记载的上次执行 anacron 的时间,将两者进行比较,如果两个时间的差值超过 anacron 的指定时间差值(一般是 1 天、7 天和一个月),就说明有定时任务没有执行,这时 anacron 会介入并执行这个漏掉的定时任务,从而保证在关机时没有执行的定时任务不会被漏掉。

在 CentOS 6.x 中,使用 cronie-anacron 软件包取代了 vixie-cron 软件包。而且在原先 CentOS 版本的 /etc/cron.{daily,weekly,monthly} 目录中的定时任务会同时被 cron 和 anacron 调用,这样非常容易出现重复执行同一个定时任务的错误。因此,在 CentOS 6.x 中,/etc/cron.{daily,weekly,monthly} 目录中的定时任务只会被 anacron 调用,从而保证这些定时任务只会在每天、每周或每月定时执行一次,而不会重复执行。

anacron命令的基本格式如下:

[root@localhost ~]# anacron [选项] [工作名]

这里的工作名指的是依据 /etc/anacrontab 文件中定义的工作名。表 1 罗列出了此命令常用的几个选项及各自的功能。

选项功能
-f强制执行相关工作,忽略时间戳。
-u更新 /var/spool/anacron/cron.{daily,weekly,monthly} 文件中的时间戳为当前日期,但不执行任何工作。
-s依据 /etc/anacrontab 文件中设定的延迟时间顺序执行工作,在前一个工作未完成前,不会开始下一个工作。
-n立即执行 /etc/anacrontab 中所有的工作,忽略所有的延迟时间。
-q禁止将信息输出到标准错误,常和 -d 选项合用。

在当前的 Linux 中,其实不需要执行任何 anacron 命令,只需要配置好 /etc/anacrontab 文件,系统就会依赖这个文件中的设定来通过 anacron 执行定时任务了。那么,关键就是 /etc/anacrontab 文件的内容了。这个文件的内容如下:

[root@localhost ~]# 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
#前面的内容和/etc/crontab类似
#the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
#最大随机廷迟,如果有大量的未执行,如果开机后立即执行可能会严重影响性能
#the jobs will be started during the following hours only
START_H0URS_RANGE=3-22
#fanacron的执行时间范围是3:00~22:00
#period in days delay in minutes job-identifier command
1 5 cron.daily nice run-parts /etc/cron.daily
#每天开机 5 分钟后就检查 /etc/cron.daily 目录内的文件是否被执行,如果今天没有被执行,那就执行
7 25 cron.weekly nice run-parts /etc/cron.weekly
#每隔 7 天开机后 25 分钟检查 /etc/cron.weekly 目录内的文件是否被执行,如果一周内没有被执行,就会执行
©monthly 45 cron.monthly nice run-parts /etc/cron.monthly
#每隔一个月开机后 45 分钟检查 /etc/cron.monthly 目录内的文件是否被执行,如果一个月内没有被执行,那就执行 

在这个文件中,“RANDOM_DELAY”定义的是最大随机延迟,也就是说,cron.daily 工作如果超过 1 天没有执行,则并不会马上执行,而是先延迟强制延迟时间,再延迟随机延迟时间,之后再执行命令;“START_HOURS_RANGE”的是定义 anacron 执行时间范围,anacron 只会在这个时间范围内执行。

我们用 cron.daily 工作来说明一下 /etc/anacrontab 的执行过程:

1. 读取 /var/spool/anacron/cron.daily 文件中 anacron 上一次执行的时间。
2. 和当前时间比较,如果两个时间的差值超过 1 天,就执行 cron.daily 工作。
3. 只能在 03:00-22:00 执行这个工作。
4. 执行工作时强制延迟时间为 5 分钟,再随机延迟 0~45 分钟。
5. 使用 nice 命令指定默认优先级,使用 run-parts 脚本执行 /etc/cron.daily 目录中所有的可执行文件。

大家会发现,/etc/cron.{daily,weekly,monthly} 目录中的脚本在当前的 Linux 中是被 anacron 调用的,不再依靠 cron 服务。不过,anacron 不用设置多余的配置,我们只需要把需要定时执行的脚本放入 /etc/cron.{daily,weekly,monthly} 目录中,就会每天、每周或每月执行,而且也不再需要启动 anacron 服务了。如果需要进行修改,则只需修改 /etc/anacrontab 配置文件即可。

比如,我更加习惯让定时任务在凌晨 03:00-05:00 执行,就可以进行如下修改:

[root@localhost ~] # 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
# the maximal random delay added to the base delay of the jobs 
RANDOM_DELAY=0
#把最大随机廷迟改为0分钟,不再随机廷迟
# the jobs will be started during the following hours only 
START_HOORS_RANGE=3-5
#执行时间范围为03:00—05:00
#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
@monthly 0 cron.monthly nice run-parts /etc/cron.monthly
#把强制延迟也改为0分钟,不再强制廷迟
```sh

这样,所有放入 /etc/cron.{daily,weekly,monthly} 目录中的脚本都会在指定时间执行,而且也不怕服务器万一关机的情况了。
 delay of the jobs 
RANDOM_DELAY=0
#把最大随机廷迟改为0分钟,不再随机廷迟
#the jobs will be started during the following hours only 
START_HOORS_RANGE=3-5
#执行时间范围为03:00—05:00
#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
@monthly 0 cron.monthly nice run-parts /etc/cron.monthly
#把强制延迟也改为0分钟,不再强制廷迟

这样,所有放入 /etc/cron.{daily,weekly,monthly} 目录中的脚本都会在指定时间执行,而且也不怕服务器万一关机的情况了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值