Linux任务计划,周期性任务执行
(我们以前已经提到过数据备份的概念了,假如在某种场景中我们需要做数据备份,将来我们可能遇到MySQL等各种各样的提供数据管理等相关的服务器程序数据,能够做数据备份,那就必然会用到这个功能。对于企业来讲最重要的是数据,数据备份是非常重要的,有的数据需要每1天或者每几个小时进行备份一次,比方说我们希望在凌晨的时候讲某个目录的数据复制一份,或者把某个临时目录比方说“/tmp”目录中的临时文件每多长时间都清理一次。这每一天都做的任务就叫周期性任务。像那种仅仅是为了某个需要将命令执行一次,那么这种任务就叫周期性计划。)
周期性计划:
在未来的某个时间点执行一次某任务:at,batch
周期性任务:
周期性运行某任务:crontab
执行结果:会通过邮件发送给用户
(对于linux来讲,周期性任务可能经常运行,任务计划也需要在外来某个时间点运行,但是任务执行时用户不在线怎么办?我们的用户没有登录并且不在线,所以一般而言这两种任务的执行结果,一旦某个任务到时间了,其执行结果会通过默认的邮件发送给用户。
这个邮件是指电子邮件的相关概念,但是不同的时,这里并不需要连接到互联网上去,发互联网上的邮箱,一般情况下,我们主机上默认会启动一个本地的邮件服务,他只用于本地主机上用户之间互相传信息的,我们以前讲过一个命令叫wall,它能够将一个信息发送给主机上的所有终端,但是像邮件的发送,这个命令就不能满足我们此处的需要了,这也很容易理解,用户没有登录上主机,那么他就不可能发送给用户,那么我们就只能通过离线消息接受的功能,来实现这种消息的传递,而邮件就是这种消息非常有效的解决方式,但是这种服务他不是为互联网上用户提供公开的公共服务的,而仅仅是保证本地主机上的用户在下一次登录以后,能够知道他此前定义的周期性任务计划或者未来某一时间点的任务在某一刻运行没有,运行的结果与否,运行的结果怎么样,我们一定要注意,这个服务一定要运行在本机上,并且也只用于本地主机上不同用户之间,互相传邮件,比方说tom给jerry发送邮件,但是jerry这个用户并没有登录,等jerry下次登录后,直接就能收到一封邮件的提示,提示说“你有一封新邮件,请注意查收”,好的,jerry只需登录自己的邮箱,然后读取自己的邮件即可,所以邮件一般有这样的效用,那么他跟我们现实中邮件的工作法则是非常相似的,当邮递员发送邮件的时候,他不可能将邮件直接放到你加的桌子上,而是找一个公共的区域,这个公共区域就是各家各户的邮筒,同样tom给jerry发送邮件的话,也是先发送给邮件服务器的,然后邮件服务器将邮件放在离线用户将来登录后能够收信的地方。
这个位置在哪呢?
我们此前讲过,在系统上每个用户在创建时,在目录 “/var/spool/mail”目录下有一个与用户同名的文件,这个个同名文件就相当于用户自己放在公共区域的邮筒,我们的邮件服务器就会将邮件数据写进这个文件中,就像相面说的,tom给jerry发送邮件,那么服务器就会将jerry要收的邮件中的数据写进/var/spool/mail/jerry文件中。那么这个工作要想工作起来,那么首先要启动本地的邮件服务,但是这个邮件服务不需要本地主机上的用户与其他主机上的用户进行通信。另外我们每一个本机用户都应该有一个与用户名同名的说法邮件的文件。
邮件服务器对于centos系列的文件系统都是默认开启的,无论是5,还是6,还是7.
我们确认本地的邮件服务器是否开启只需运行命令:
“ss -tnl”
或者运行:
“netstat -tnl”
如果发现有一个25号端口处于监听的状态,那么就表示本机的邮件服务是正常的,正处于监听状态,对于cenots5来讲用的是postfix6,对于centos6来讲是postfix7
我们还可以使用“netstat -tnlp”可以看到这个邮件服务器程序在监听。
[[email protected] mail]# netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 2703/master
tcp 0 0 ::1:25 :::* LISTEN 2703/master //master是邮件服务器中的一个主控进程用来监听25号端口,并看到25前面是127.0.0.1那么就是代表本地主机上为各用户之间传递邮件做准备。
[[email protected] mail]#
)
本地电子邮件服务:
smtp:simple mail transmission protocol(简单邮件传输协议)是一个应用层协议, 他只能实现用户发邮件,不能收邮件
POP3:邮局协议:Post Office Procotol
imap4:互联网邮件访问协议:Internet Mail Access Proctol
在本地主机上实现邮件收发服务:
直接使用mail命令即可,mail也属于一个文本行的MUA(邮件用户代理)
mail命令:
centos6上使用的是mail,但是centos7上使用的是mailx
MUA:Mail User Agent,用户收发邮件的工具程序;
要想使用mail命令或者mailx命令来实现发送邮件,实现发送邮件。
格式:
可以直接写一个mail即可因为他是一个连接,也可以先一个完成的
mailx [-s‘SUBJECT‘] username[@hostname]
解释:
‘SUBJECT‘是邮件标题
username:表示要发送给的用户名
@hostname:表示域名或者主机名,如果是本地主机上的用户之间发邮件,这 个域名可以省略
邮件正文的生成:
(1)交互式输入;点号“.”单独成行可以表示正文结束;ctrl+d提交也可
(2)通过输入重定向;
(3)通过管道; //主要是在我们将一个命令的结果作为邮件的正文发送给对方 时,我们使用管道。
演示收发本地邮件:
[[email protected] ~]# mail -s ‘hello dong‘ [email protected] //发送本地邮件时,@主机名可以省 略,回车后就表示开始输入邮件的正文。
你好!想你了哈哈。。。。
. //邮件正文输入后,然后另起一行输入点号“.”,表示结束
EOT
[[email protected] ~]# su - dong
[[email protected] ~]$ mail //输入mail打开自己的邮箱,mail不带任何选项时,表示收邮件
Heirloom Mail version 12.4 7/29/08. Type ? for help.
"/var/spool/mail/dong": 1 message1 new
>N 1 root Wed Nov 16 12:29 18/713 "hello dong" //N:表示新邮件;1:表示新邮件的编号;
& 1 //我们要想查看新邮件,只需输入新邮件的编号
Message 1: //这灰色的表示邮件的收发信息
[email protected] WedNov 16 12:29:26 2016 //发件人是谁,发 送的时间
Return-Path:<[email protected]> //恢复的话恢复给谁
X-Original-To:[email protected]
Delivered-To:[email protected]
Date:Wed, 16 Nov 2016 12:29:25 +0800
To:[email protected]
Subject:hello dong //邮件标题
User-Agent:Heirloom mailx 12.4 7/29/08 //对方发邮件是用的什么程序
Content-Type:text/plain; charset=utf-8 //邮件正文是什么格式
From:[email protected] (root)
Status:R
你好!想你了哈哈。。。。
& q //退出
Held 1 message in /var/spool/mail/dong
You have mail in /var/spool/mail/dong //这里还显示我们还有邮件
[[email protected] ~]$
另外我们可否自动给一个邮件正文呢?
一般情况下我们在命令行下输入mail命令后,我们是在交互式模式下输入正文,这样就不太容易写脚本,我们写脚本时要尽量避免与用户交互,只要是通过标准输入接收输入的,我们都可以通过管道或者重定向的方式来实现。
举例演示:
自动输入邮件内容
[[email protected] ~]# mail -s ‘fstab file‘ xiang < /etc/fstab //这条命令还可以这样写:
[[email protected] ~]# cat /etc/issue | mail -s ‘issue file‘ dong
[[email protected] ~]# su - xiang
[[email protected] ~]$ mail
Heirloom Mail version 12.4 7/29/08. Type ? for help.
"/var/spool/mail/xiang": 1message 1 new
>N 1 root Wed Nov 1612:54 33/1573 "fstab file"
& 1
Message 1:
[email protected] WedNov 16 12:54:39 2016
Return-Path:<[email protected]>
X-Original-To: xiang
Delivered-To:[email protected]
Date: Wed, 16 Nov 2016 12:54:39 +0800
To: [email protected]
Subject: fstab file
User-Agent: Heirloom mailx 12.4 7/29/08
Content-Type: text/plain; charset=us-ascii
From: [email protected](root)
Status: R
#
# /etc/fstab
# Created by anaconda on Tue Oct 1112:39:17 2016
#
# Accessible filesystems, by reference, aremaintained under ‘/dev/disk‘
# See man pages fstab(5), findfs(8),mount(8) and/or blkid(8) for more info
#
UUID=2ead7599-15b0-4b11-b96d-5f9b59e2e7eb/ ext4 defaults
11
UUID=edb28e3e-5ee7-400f-8226-fab5fa157188/boot ext4 defaults
12
UUID=32376552-a128-416d-be08-0aa6acab4661/testdir ext4 defaults
12
UUID=091e5b14-8201-4ffc-9278-41b7acae00d9swap swap defaults
00
tmpfs /dev/shm tmpfs defaults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
sysfs /sys sysfs defaults 0 0
proc /proc proc defaults 0 0
&
At EOF
&
At EOF
& q
Held 1 message in /var/spool/mail/xiang
[[email protected] ~]$
at命令:
格式:
at [OPTION]... TIME
时间表示格式TIME:
(1)HH:MM[YYY-mm-dd]:表示指明小时分钟
举例:现在是11:28了,如果我想表示11:10,会表示在下一个11:10执行计划任务。
如果我们想表示年月日的话,那么我们就这样给出:
11:102016-11-16
(2)模糊时间表示法:
noon(正午12点)
midnight(午夜表示晚上12点)
teatime(下午茶是下午4点)
tomorrow
(3)相对时间表示法:
now+# //从现在开始往后走一周。
#表示数字然后后面加上单位
单位UNIT有:minutes,hours,days, weeks
at的作业有队列概念,用单个字符表示,默认都使用a队列;并且作业的编号使用绝对编号。
(当主机上有多个用户都设置了多个作业,那么我们可以根据用户不同讲作业分别放在不同的队列中,比方说a,b,c......等来表示不同对列)
常用的选项:
-l:查看作业队列,也就是查看提交的还未执行的作业,相当于atq,当作业执行 后就看不到了。
-f /PATH/FROM/SOMEFILE:从指定文件中读取作业任务,而不用再交互式输入;
(如果有一些命令经常性的执行,只是在某些时间点进行,并不是周期性的,什么时间点用到时我们可以将这个命令写在一个文件中,用选项“-f”来读取即可。)
-d:当一个作业提交了还未执行,现在想删除指定的作业;就使用选项-d后面跟作 业号,相当于使用atrm命令
-c:查看at命令作业的执行内容,当我们忘记时,就是用选项“-c”然后面跟上作 业号,这个过程中显示的出的内容包括,前面显示的是at执行环境,也就是 说at执行是在某一个环境中执行的。在文件最底下是显示作业的具体内容。
-q QUEUE:指明队列;
注意:
(1)作业的执行结果是以邮件方式,发送给提交作业的用户;
(2)at命令也能执行脚本,所以我们只要给定脚本路径就可以了,我们要记得是at有自己的运行环境,在我们自己交互式运行环境下可能不一样,所以有些命令需要我们给出全路径才能执行。
举例演示:
在at后面输入的内容既可以是一个脚本,也可以是任何一条命令,当我们将需要执行的命令写完了,我们使用“ctr+d”提交
举例演示:
at读取作业文件
(1)先用命令查看是否有作业还未执行:
at -l 或 atq
(2)切换到/tetstdir目录下,并创建一个作业文件,文件内容为:
vim zuoye
文件内容:
cat /etc/issue
echo "tianxiang i love you."
(3)执行at读取作业文件设计计划任务
at -f /testdir/zuoye now+1min
(4)用at -l 或 atq查看未执行的作业
(5)等过了作业执行时间后,验证一下
[[email protected] testdir]# mail
Heirloom Mail version 12.4 7/29/08. Type ? for help.
"/var/spool/mail/root": 3messages 1 new
1root Wed Nov 1614:51 17/621 "Output from your job "
2root Wed Nov 1614:55 26/692 "Output from your job "
>N 3 root Wed Nov 1615:20 17/631 "Output from your job "
& 3
Message 3:
From [email protected] Wed Nov 16 15:20:01 2016
Return-Path:<[email protected]>
X-Original-To: root
Delivered-To:[email protected]
Subject: Output from your job 10
To: [email protected]
Date: Wed, 16 Nov 2016 15:20:01 +0800 (CST)
From: [email protected](root)
Status: R
CentOSrelease 6.8 (Final)
Kernel\r on an \m
tianxiangi love you
& q
Held 3 messages in /var/spool/mail/root
[[email protected] testdir]#
batch命令:
batch会让系统自行选择在系统资源较空闲的时间去执行指定的任务;
周期性任务计划:
(crontab更多的时候我们应用的是cron,那我们怎样才能做到周期性执行某任务呢?什么是连续时间什么是不连续时间,想象一下,我们现在定义了好多的任务,有连续的,也有不连续的,这就意味着我们必须有一种机制,确保在某个时间点到达时,这个任务就提交。所以说有那么一种机制,必须保证每时每刻随时观测着,看看有哪些任务该提交了,那么谁来做这件事呢?我们需要一个服务,随时处于运行状态,而这个服务他将一直运行在后台,在每一个时间点不断的检查有哪些任务该执行了,这就需要一个服务程序不间断的,去监听去查看对应的时间点是否满足条件,然后让其运行。这种服务程序对于我们的系统来讲,一般靠的就是程序包,这个程序包叫做cronie,这个包中有两个程序包其中, cronie:这是一个主程序包,提供了crond守护进程及相关辅助工具;真正提供服务的是这个叫crond的文件。)
服务程序:
cronie:主程序包,提供了crond守护进程及相关辅助工具;
确保crond守护进程(daemon)处于运行状态;
(对于centos5 和centos6, centos7还不一样
CentOS7:
systemctl status crond.service //crond后面的“.service”可以省略
显示:active(running)表示正常
也可以执行:service crond status
CentOS6:
service crond status
显示:isrunning..表示正常
CentOS5:执行的命令跟centos6一样
在centos7系统上我们需要使用
“systemctl status crond.service”这个命令来来查看这个服务的状态:如果出现一个绿色的active(running)则表示这个服务是正常的,也可以在centos7上使用centos6上的命令:
“service crond status”
在centos6上执行命令
是:“service crond status”显示“is running....”表示这个服务正常运行
[[email protected] testdir]# service crond status
crond (pid 2819) is running...
[[email protected] testdir]#
)
只有crond这个服务能够正常运行,才能确保我们之后定义的周期性任务计划能够完成。
所以周期任务也需要像cat那样提供任务作业给crond
但是向crond提交作业的方式不同于at,他需要使用专用的配置文件,此文件有固定格式,并且不建议直接使用文本编辑器直接编辑此文件;要使用crontab命令。
(原因就是使用vim编辑器直接编辑此文件的话,不能进行语法格式的检查,而使用crontab命令,会自动进行语法检查,一旦发现文件中的语法错误,他会拒绝提交文件,或者提醒用户文件中有语法错误,)
cron任务分为两类:
系统cron任务:主要用于实现系统自身的维护。
(比方说/tmp目录下本来就是临时文件,如果这些临时文件创建超过一 个月,那我们需要清除这些临时文件,这就是系统自身的维护操纵,而 这种任务都是允许在系统安装完成后,自动运行的。对于系统任务我们 不能使用crontab命令,而是手动编辑配置文件)
手动编辑配置文件:/etc/crontab文件(现在基本都不需要手动编辑了)
用户cron任务:用户手动编辑任务文件,根据自身需要写的任务。
命令:crontab命令
系统cron的配置格式:
[[email protected] ~]# cat /etc/crontab
SHELL=/bin/bash //前面这些不带#的都是定义环境变量的,定义哪种SHELL来运行脚本
PATH=/sbin:/bin:/usr/sbin:/usr/bin //到哪些路径下找我们的命令,这里定义的路径很少,但是我们系统上的PATH路径很多,所以我们一定要注意的是,有很多命令在往cron文件写的时候,上面的PATH路径可能是不够用的,所以导致的结果是很多时候我们的命令需要些绝对路径。甚至我们自己写的脚本,脚本的运行也应用的是上面定义的PATH,也就意味着我们的脚本中的命令也就只能识别到上面的PATH路径,如果没有的,我们就需要自定义PATH路径,或者写命令的绝对路径,在脚本中。
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
[[email protected] ~]#
注意总结:系统cron指定的配置。
(1)每一行定义一个周期性任务一共有 七个字段;前五个定义时间,第六个定义身份,最后一个表示指定任务的。
“* * * * *”前五个用空格隔开的五个字段表示定义周期性时间;
user-name:运行任务的用户身份
commandto be executed:任务
(2)此处的环境变量不同于用户登录后获得的环境,因此,建议命令使用绝对路径, 或者自定义PATH环境变量;
(3)执行结果邮件发送给MAILTO指定的用户;
用户cron的配置格式:
用户cron的配置文件是/var/spool/cron/USERNAME文件
其中/var/spool/cron/USERNAME //这个大写就表示要替换的用户名,也就 是表示新建的cron已经是以新用户身份
进行运行,所以命令中就不需要用户名了
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) //第一个星号*表示分钟,取值范围为0-59
# | .------------- hour (0 - 23) //第二个星号*表示小时,取值范围为0-23
# | | .---------- day of month (1 -31) //第三个星号*表示天,其值范围为1-31
# | | | .------- month (1 - 12) OR jan,feb,mar,apr... //表示月,其实范围为1-12
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | | //最后一个星号*表示星期几,0和7都表示周日。我们也可以使用星 期的英文简写来表示
# * * * * * user-name command to be executed //在用户cron文件中没有用户 名,因为对于用户而言谁编辑的就发给谁
注意:
(1)每行定义一个cron任务,共6个字段;比系统cron文件中少了一个“user-name”
(2)此处的环境变量不同于用户登录后获得的环境,因此,建议命令使用绝对路径, 或者自定义PATH环境变量;
(3)邮件发送给当前用户;
上面已经从空间上大体已经说明了,接下来说一下cron文件中的时间点怎样指;
时间表示法:对系统cron和用户cron都是通用的
注意:
(1)特定值:
给定时间点有效取值范围内的值;
注意:day of week(星期几)和day of month(月)一般不同时使用;
(2)*
星号*有特殊意义,表示:给定的时间点上有效取值范围内的所有值;
比方说,在分钟的*上写分钟时,其取值范围为1-59;所以也可以说 *是通配符。这样写就表示:“每什么什么,在分上就表示没分,在时 上就表示每小时,在天上就表示每天,在月上,就表示每月,在周上 就表示每周”
(3)离散取值:使用逗号隔开“,”
在中间时间点上使用逗号分隔的多个数值;#,#,#
(4)连续其值:使用减符号“-”#-#
(5)在指定的时间范围上,定义步长;使用“/”表示;
在指定的时间内,控制
/#:#即步长
*/2:每多少,执行一次任务;
举例演示:
(1)3 * * * *:(每小时执行一次)表示每小时第三分钟执行一次 ;
这个“3”表示几点的3分,也就是每小时三分钟。
总结:当我们说每多少的时候,我们就找时间点单位最小的那个*即可。
(2)3 4 * * 5:(每周执行一次)表示每周五的4点3分;(表示每周执行一 次)
这里要注意,月给了周就不要给了,周给了月就不要给了。
(3)5 6 7 * *:(每月执行一次)表示每月的7日6点5分执行一次;
(4)7 8 9 1 0 *:(每年执行一次)表示每年的10月9日每年的10月9日 8点七点半
(5)9 8 * * 3,7: 每周三和周日上午八点九分执行;
(6)0 8,20 * * 3,7:每周三和周日上午和下午八点9分;
(7)0 9-18 * * 1-5:工作时间内每小时运行;
(8)*/5 * * * * :表示每5分钟执行一次计划任务;
(9)*/7 * * * :表示每多少分钟执行一次
注意:
(1)指定的时间点不能被步长整除时,其意义将不复存在。
(2)对于crontab最小时间单位为分钟。完成“秒”级任务,得需要额外借助于 其他的机制;
定义每分钟任务,而在利用脚本实现在每分钟之内,循环执行多少次;
crontab命令:
格式:
crontab [-u user] [-l | -r | -e] [-i] [-s]
选项:
-e:编辑任务;
举例:crontab -e 直接回车就打开一个文件,直接编辑即可
-l:列出所有任务;
-r:移除所有任务;即删除文件/var/spool/cron/USERNAME文件;
如果只想删除其中某一个任务,那就直接crontab -e重新编辑文件,把要删的那 一行删除或者加上注释即可。
-i:在使用-r选项移除所有任务时提示用户确认;
-u user:root用户可为指定用户管理cron任务;
举例:crontab -u dong -e
举例:
在用户cron的配置文件中,我们手动编辑一个配置文件。
* * * * * /bin/echo "hello!" 这表示每分钟输出一个hello!
注意:运行结果以邮件方式通知给当前用户,如果拒绝接收邮件;
(1)COMMAND >/dev/null
(2)COMMAND &> /dev/null
注意:定义COMMAND时,如果命令需要用到%,需要对其转义;但放置于单引号中的%不用转义亦可;
思考:
某任务在指定的时间因关机未能执行,下次开机会不会自动执行?
解:
不会!
如果期望某时间因故未能按时执行,下次开机后无论是否到了响应的时间点都 要执行一次,可使用anacron实现;
课外作业:anacron及其应用;
练习:
1.每12小时备份一次/etc/目录至/backups目录中,保存文件称格式为 “etc-yyyy-mm-dd-hh.tar.xz”
2.每周2,4,7备份/var/log/secure文件至/logs目录中,文件名格式为 “secure-yyyymmdd”
3.每两小时取出当前系统/proc/meminfo文件中以S或M开头的行信息追加至 /tmp/meminfo.txt文件中;