12.20 Linux循环执行定时任务(crontab命令)

网友投稿 1042 2022-05-29

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

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

crond 服务的启动和自启动方法如下:

[root@localhost ~]# service crond restart 停止 crond: [确定] 正在启动 crond: [确定] \#重新启动crond服务 [root@localhost ~]# chkconfig crond on \#设定crond服务为开机自启动

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

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

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

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

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

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

crontab 命令的基本格式如下:

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

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

与此同时,表 1 罗列出了此命令常用的选项及功能。

其实 crontab 定时任务非常简单,只需执行“crontab -e”命令,然后输入想要定时执行的任务即可。不过,当我们执行“crontab -e”命令时,打开的是一个空文件,而且操作方法和 Vim 是一致的。那么,这个文件的格式才是我们真正需要学习的内容。文件格式如下:

[root@localhost !]# crontab -e \#进入 crontab 编辑界面。会打开Vim编辑你的任务 \* * * * * 执行的任务

这个文件中是通过 5 个“” 来确定命令或任务的执行时间的,这 5个 “” 的具体含义如表 2 所示。

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

当“crontab -e”编辑完成之后,一旦保存退出,那么这个定时任务实际就会写入 /var/spool/cron/ 目录中,每个用户的定时任务用自己的用户名进行区分。而且 crontab 命令只要保存就会生效,只要 crond 服务是启动的。知道了这 5 个时间字段的含义,我们多举几个时间的例子来熟悉一下时间字段,如表 4 所示。

现在我们已经对这 5 个时间字段非常熟悉了,可是在“执行的任务”字段中都可以写什么呢?既可以定时执行系统命令,也可以定时执行某个 Shell 脚本,这里举几个实际的例子。

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

[root@localhost ~]# crontab -e \#进入编辑界面 */5 * * * * /bin/echo "11" >> /tmp/test

这个任务在时间工作中没有任何意义,但是可以很简单地验证我们的定时任务是否可以正常执行。如果觉得每隔 5 分钟太长,那就换成“*”,让它每分钟执行一次。而且和 at 命令一样,如果我们定时执行的是系统命令,那么最好使用绝对路径。

【例 2】让系统在每周二的凌晨 5 点 05 分重启一次。

[root@localhost ~]# crontab -e 5.5 * * 2 /sbin/shutdown -r now

如果服务器的负载压力比较大,则建议每周重启一次,让系统状态归零。比如绝大多数游戏服务器每周维护一次,维护时最主要的工作就是重启,让系统状态归零。这时可以让我们的服务器自动来定时执行。

【例 3】在每月 1 日、10 日、15 日的凌晨 3 点 30 分都定时执行日志备份脚本 autobak.sh。

[root@localhost ~]# crontab -e 30.3 1,10,15 * * /root/sh/autobak.sh

这些定时任务保存之后,就可以在指定的时间执行了。我们可以使用命令来查看和删除定时任务,命令如下:

12.20 Linux循环执行定时任务(crontab命令)

[root@localhost ~]# crontab -l \#查看root用户的crontab任务 */5 * * * * /bin/echo "11" >> /tmp/test 5.5 * * 2 /sbin/shutdown -r now 30.3 1,10,15 * * /root/sh/autobak.sh [root@localhost ~]# crontab -r \#删除root用户所有的定时任务。如果只想删除某个定时任务,则可以执行“crontab -e”命令进入 \#编辑模式手工删除 [root@localhost ~]# crontab -l no crontab for root \#删除后,再查询就没有root用户的定时任务了

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

6 个选项都不能为空,必须填写。如果不确定,则使用“*”代表任意时间。

crontab 定时任务的最小有效时间是分钟,最大有效时间是月。像 2018 年某时执行、3 点 30 分 30 秒这样的时间都不能被识别。

在定义时间时,日期和星期最好不要在一条定时任务中出现,因为它们都以天为单位,非常容易让管理员混淆。

在定时任务中,不管是直接写命令,还是在脚本中写命令,最好都使用绝对路径。有时使用相对路径的命令会报错。

系统的crontab设置

“crontab -e”是每个用户都可以执行的命令,也就是说,不同的用户身份可以执行自己的定时任务。但是有些定时任务需要系统执行,这时就需要编辑 /etc/crontab 这个配置文件了。

当然,并不是说写入 /etc/crontab 配置文件中的定时任务在执行时不需要用户身份,而是“crontab -e”命令在定义定时任务时,默认用户身份是当前登录用户。而在修改 /etc/crontab 配置文件时,定时任务的执行者身份是可以手工指定的。这样定时任务的执行会更加灵活,修改起来也更加方便。

那我们打开这个文件看看吧,如下:

[root@localhost ~]# vi /etc/crontab SHELL=/bin/bash \#标识使用哪种Shell PATH=/sbin:/bin:/usr/sbin:/usr/bin \#指定PATH环境变量。crontab使用自己的PATH,而不使用系统默认的PATH,所以在定时任务中出现的 \#命令最好使用大写 MAILTO=root \#如果有报错输出,或命令结果有输出,则会向root发送信息 HOME=/ \#标识主目录 \# For details see man 4 crontabs \#提示大家可以去“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 \#分 时日月周执行者身份命令 \#列出文件格式,并加入了注释

在 CentOS 6.x 中,/etc/crontab 文件也发生了变化。在 CentOS 5.x 中,这个文件的内容大概是这样子的:

\#以下输出在CentOS 5.5中 [root@sc ~]# vi /etc/crontab SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root HOME=/ \# run-parts 01 * * * * root run-parts /etc/cron.hourly 02.4 * * * root run-parts /etc/cron.daily 22.4 * * 0 root run-parts /etc/cron.weekly 42.4 1 * * root run-parts /etc/cron.monthly

在 CentOS 5.x 中,/etc/crontab 文件会使用 run-parts 脚本执行 /etc/cron.{daily,weekly,monthly} 目录中的所有文件。这个 run-parts 其实是一个 Shell 脚本,保存在 /usr/bin/run-parts 中,它的作用就是把其后面跟随的目录中的所有可执行文件依次执行。也就是说,如果我们想让某个脚本在每天都执行一次,那么可以不用手工去写定时任务,而只需要给这个脚本赋予执行权限,并把它放入 /etc/cron.daily/ 目录中,这样这个脚本就会在每天的凌晨 4 点 02 分执行了。

但是在 CentOS 6.x 中,/etc/crontab 文件中不再有相关的段落,那么 run-ptars 这种定时任务的执行方法是否不可用了呢?

我们看到 /etc/crontab 中有一句提示,让我们“man 4 crontabs”来查看帮助,那么我们就看看这个帮助吧!在这个帮助中,写明了“在旧版本的 crontab 配置文件中,通过 run-parts 脚本来调用 cron.{daily,weekly,monthly} 目录,定时执行这些目录中的脚本。在当前系统中,为了避免 cron 和 anacron 之间产生冲突,只要 anacron 已经安装,就使用 anacron 来执行这些目录中的脚本。具体可以查看 anacron(8) 的帮助”。对于 anacron 的用法,后续章节再详解介绍。

其实,对用户来讲,并不需要知道这个定时任务到底是由哪个程序调用的。我们需要知道的事情是如何使用系统的 crontab 设置。对此,新、老版本的 CentOS 没有区别,配置方法都有两种。

第一种方法就是把需要定时执行的工作写成脚本程序,并赋予执行权限,然后直接把这个脚本复制到 /etc/cron.{daily,weekly,monthly} 目录中的任意一个。比如,我需要让某个脚本每周执行,就把这个脚本复制到 /etc/cron.weekly/ 目录中。这样这个脚本就会每周执行一次,具体的执行时间要参考 anacron 的配置文件。

第二种方法就是修改 /etc/crontab 这个配置文件,加入自己的定时任务,不过需要注意指定脚本的执行者身份。例如:

[root@localhost ~]# vi /etc/crontab …省略部分输出… \* * * * * root run-parts /root/cron/ \#让系统每分钟都执行一次/root/cron/目录中的脚本,脚本执行者是root用户 \#虽然在CentOS 6.x中不直接通过此配置文件调用/etc/cron.{daily,weekly,monthly}这些目录,但是run-parts脚本还是可以使用的。所以我完全可以参照CentOS 5.x的方法来写定时任务 \#使用run-parts脚本调用并执行/root/cron/目录中所有的可执行文件 [root@localhost ~]# mkdir cron \#建立/root/cron/目录 [root@localhost cron]# vi /root/cron/hello.sh \#/bin/bash echo "hello" >> /root/cron/hello.log \#在/root/cron/hello.log文件中写入“hello” [root@localhost cron]# chmod 755 hello.sh \#赋予执行权限 \#因为hello.sh脚本放入了/root/cron/目录中,所以每分钟执行一次。

只要保存 /etc/crontab 文件,这个定时任务就可以执行了。当然要确定 crond 服务是运行的。

这两种方法都是可以使用的,具体看个人的习惯。不过,要想修改 /etc/crontab 文件,必须是 root 用户,普通用户不能修改,只能使用用户身份的 crontab 命令。

Linux

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:CVE-2022-0847 DirtyPipe漏洞分析
下一篇:linux的systemd与init的区别
相关文章