查看原文
其他

进程管理与计划任务(5)-crontab

Cloud研习社 Cloud研习社 2023-06-06


每周二、四、六定期更新,我们不见不散!


计划任务,也叫定时任务 - 周期性执行任务,常用于执行定时任务的进程是crond。

使用定时任务,可以每天,每小时按照需求重复执行每个任务

例如:我们工作中需要每天对数据进行备份,为了不影响业务,需要在每天的凌晨2点开始,备份结束基本就是凌晨4点多了,但是你总不能每天都凌晨起来做备份工作吧。这个时候写一个自动化的程序实现自动备份非常重要,针对这个备份任务,crond就派上用场了。

当然,除了要求每天备份的这种重复性的工作以外,一些在特定的时间点执行一次的任务也可以做到自动化,类似于我们的手机闹钟,可以设置明天早上只响一次,以后这个闹钟就不会再响了。

用户定时任务三个主要的名词解释

  • cron是定时任务软件名;
  • crond是定时任务进程名,真正实现定时任务的服务;
  • crontab是设置定时任务的工具;

我们看看定时任务怎么使用:

要想使用定时任务,我们需要保证能执行定时任务的crond服务已经启动:

[root@studyclub ~]# systemctl status crondcrond.service - Command Scheduler
   Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2021-06-19 13:56:26 CST; 1 day 20h ago
 Main PID: 6165 (crond)
   CGroup: /system.slice/crond.service
           └─6165 /usr/sbin/crond -n

Jun 19 13:56:26 studyclub systemd[1]: Started Command Scheduler.
Jun 19 13:56:26 studyclub crond[6165]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 5% if used.)
Jun 19 13:56:26 studyclub crond[6165]: (CRON) INFO (running with inotify support)


如果上面的返回结果中有active(running)的字样,说明crond服务已经启动了,我们可以正常设置定时任务。如果没有active(running)的字样,我们需要启动定时任务:


[root@studyclub ~]# systemctl start crond

# 为了方便后续的使用,我们把crond设置为开机自启动
[root@studyclub ~]# systemctl enable crond


好了,服务启动了,下面我们就来看怎么添加自己的定时任务:

crontab是设置定时任务的工具,我们先看看crontab的用法:

crontab :
-l        list
-e        edit
-u user 查看特定用户的定时任务(了解即可)


crontab设置定时任务以后,需要把用户设置的任务信息保存下来,这些信息就保存在:/var/spool/cron/中,每个用户设置的任务信息保存成一个文件,这个文件以用户名作为文件名。也就是说,如果jason用户添加了定时任务,那么这些定时任务的信息都会保存在/var/spool/cron/jason文件中。编辑定时任务我们通过crontab -e命令来完成,其实这个命令就等同于vim /var/spool/cron/jason。但是我们不这么做,使用crontab -e命令才是正道,因为定时任务有一些语法要求,使用crontab -e在一定程度上可以避免语法书写错误。
编写定时任务的语法:


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
| | | | |
* * * * * (command to be executed

共六列
第一列:分钟(0-59
第二列:小时(0-23
第三列:日(1-31
第四列:月(1-12)
第五列:周(0-6)
第六列:要执行的任务


特殊符号星号"*": 在定时任务里代表“每一”
特殊符号减号" -":连续区间 1-10
特殊符号逗号"," :列举1,2,3,4
/n:n是数字,即每隔n单位时间,例如每20分钟执行一次:*/20


# 练习1:
*/1 * * * * /bin/sh /scripts/data.sh
说明:*代表“每一”,第一列的意思为分钟,特殊符号“/”表示每隔的意思。那么上面这个任务就是每隔一分钟,每小时,每日,每月,每周都执行后面的命令。说人话就是:每隔一分钟执行/bin/sh /scripts/data.sh程序。
# 练习2:
30 3,12 * * * /bin/sh /scripts/jason.sh
说明:第一列是30分,第二列是3和12,代表3时和12时,所以这个任务是每天的3时30分和12时30分执行/scripts/jason.sh脚本
# 练习3:
30 */6 * * *    /bin/sh /scripts/jason.sh
说明:第一列为30,表示30分;第二列*/6代表每6隔小时,也相当于 “6,12,18,24 ”的作用。这个定时任务的意思是每隔6个小时的半点时刻执行/scripts/jason.sh脚本。
# 练习4:
30 8-18/2 * * * /bin/sh /scripts/jason.sh
说明:第一列为30,表示30分;第二列8-18/2,表示8时-18时之间,每隔2小时,相当于"8,10,12,14,16,18"的写法,那么,此定时任务的意思就是8点到18点之间,每隔2小时的半点时刻执行jason.sh 脚本。
# 练习5:
45 4 1,10,22 * * /application/apache/bin/apachectl graceful
说明:每月的1、10、22日的凌晨4:45分重启apache服务器(这种重启方式不会中断原有的连接)
# 练习6:
10 1 * * 6,0 /application/apache/bin/apachectl graceful
说明:表示每周六、周日的凌晨1 : 10分重启apache。(星期日可以用0表示也可以用7表示)
# 练习7:
0,30 18-23 * * * /application/apache/bin/apachectl graceful
说明:表示每天的18时-23时的整点和半点都重启apache
# 练习8:
00 */1 * * * /application/apache/bin/apachectl graceful
说明:每个小时的整点重启apache
# 练习9:
* 23,00-07/1 * * * /application/apache/bin/apachectl graceful # 注意防止犯错:每小时执行还是每分钟执行,注意第一个字段
说明:23点以及0点-7点每隔一小时重启一次apache
# 练习10:
00 */1 * * *  /application/apache/bin/apachectl graceful
说明:每隔一小时的整点重启apache


好了,通过上面的10个练习例子,我们已经了解了定时任务的书写方式。下面我们来真正的把上面的任务写到定时任务里。
配置定时任务:
# 每分钟向/mnt/crontab.log 文件追加welcome to studyclub字符串
[root@studyclub ~]# crontab -e

# 2021年6月21日13:26:15 this is a test instance
* * * * * echo "welcome to studyclub" >> /mnt/crontab.log


上面编辑完成后,按Esc键退出编辑模式,“:wq”保存并退出。(实际上这个操作和vim的操作是完全一致的)
我们再来看一个例子:
  • 每天0点把/var/www/html打包备份到/mnt下,并且备份文件名不同。

我们知道定时任务是由执行时间和任务命令组成的,我们先来看看这个任务的执行命令应该怎么写。


[root@studyclub ~]# tar -jcf /mnt/html_$(date +%F-%T).bz2 /var/www/html/ # 如果没有/var/www/html/目录,可以自行创建
tar: Removing leading `/' from member names
[root@studyclub ~]# ll /mnt # 验证命令执行成功,备份文件已经生成
-rw-r--r-- 1 root root 170 Jun 21 13:18 html_2021-06-2113:18:31.bz2


好了,命令已经写好了,接下来我们来书写定时任务:


[root@studyclub ~]# crontab -e

# 2021年6月21日13:26:15 this is a test instance
* * * * * echo "welcome to studyclub" >> /mnt/crontab.log

#
* * * * * tar -jcf /mnt/html_$(date +%F-%T).bz2 /var/www/html/ # 为了方便检查我们写的对不对,所以写成了每分钟执行一次


上面编辑完成后我们保存、退出,一分钟后去/mnt目录发现没有新的文件生成。这是什么问题呢?我们看看crond的日志吧,它在/var/log/cron下有一段信息:

Jun 21 14:11:01 studyclub CROND[9892]: (root) CMD (tar -jcf /mnt/html_$(date +)


这里面我们看不到任何error字样的信息,但是我们看到最后小括号里的命令是tar -jcf /mnt/html_$(date +,这显然不是我们希望的执行的命令,为什么我们的命令在“+”号处就被节断了呢?这是因为crond里要求对%做转义,即需要写成“\%”,所以我们改成下面这样:
[root@studyclub ~]# crontab -e

# 2021年6月21日13:26:15 this is a test instance
* * * * * echo "welcome to studyclub" >> /mnt/crontab.log

#
* * * * * tar -jcf /mnt/html_$(date +\%F-\%T).bz2 /var/www/html/ # 修改后的效果


这个时候每过一分钟我们就可以看到周期任务生成的备份文件了。看到生效以后,我们可以把定时任务前两列的“*”都改成“0”,即每天的0点做备份。
经过这个例子我们发现,命令行执行成功的命令,在crond里执行不一定成功,所以为了避免这种特殊符号引起的问题,我们可以把命令写到一个脚本文件中,在crond里只需要执行脚本文件就可以了,这样就不存在因为特殊符号等原因引起的错误了。所以上面的例子我们还可以这么做:

[root@studyclub ~]# cat bak.sh
#!/bin/sh
cd /var/www/
tar -jcf /mnt/html_$(date +%F-%T).bz2 html/ &>/dev/null

[root@studyclub ~]# crontab -e
0 0 * * * /bin/sh /root/bak.sh


我们在总结一点crontab书写要领:
  • 要领1:为定时任务规则加必要的注释

  • 要领2:所有的定时任务尽量都以脚本的形式执行

  • 要领3:在执行的Shell脚本前加上/bin/sh

  • 要领4:定时任务中命令或脚本的结尾加>/dev/null 2>&1  或 &>/dev/null

  • 要领5:定时任务是以用户为单位执行的,在指定用户下执行相关定时任务

  • 要领6:生产任务计划程序中不要随意打印输出信息,有输出信息的需要通过重定向让它不显示。

  • 要领7:定时任务执行的脚本要存放到规范路径下(我们一般是创建目录/server/scripts,自己写的脚本文件都放在这)

  • 要领8:配置定时任务要规范操作过程,减少出错。首先在命令行测试要执行的命令是否可以成功执行,测试通过后再写到crontab配置文件里,如果命令里有特殊字符,可以把命令封装成脚本,在crontab编辑定时任务的时候,执行脚本就可以了。

  • 要领9:定时任务脚本中程序命令及路径尽量用全路径

  • 要领10:时间变量%号要用反斜线转义

  • 要领11:出错或无法执行,就检查/var/log/cron日志

课后习题:
  1. 每分钟向/mnt/crontab.log 文件追加jason字符串

  2. 8点到12点之间每5分钟向/mnt/crontab.log 文件追加james字符串

  3. 在每周6的凌晨3:15执行/home/shell/collect.pl,并将标准输出和标准错误输出到/dev/null设备,请写出crontab中的语句。

  4. crontab在11月份内,每天的早上6点到12点中,每隔2小时执行一次/usr/bin/httpd.sh,怎么实现 ?

  5. crontab文件由六个域组成,每个域之间用空格分割,其排列正确的为( )    A、MIN HOUR DAY MONTH YEAR COMMAND    B、MIN HOUR DAY MONTH DAYOFWEEK COMMAND    C、COMMAND HOUR DAY MONTH DAYOFWEEK    D、COMMAND YEAR MONTH DAY HOUR MIN



新手应知:

    尝鲜Rocky Linux

《Linux基础及进阶》:

    039 - 文件打包与压缩(4)-dd命令详解    040 - 进程管理与计划任务(1)-进程管理与job control    041 - 进程管理与计划任务(2)-工作的前后台管理    042 - 进程管理与计划任务(3)-nohup、ps、top、pstree    043 - 进程管理与计划任务(4)-uptime\free\htop


看完本文有收获?请分享给更多人


推荐关注「Cloud研习社」,带你从零开始掌握云计算技术!

微信号|bjdream-1


Cloud研习社 · 


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存