您的位置:首页 > 运维架构 > Linux

Linux基础之任务计划(at,crontab)

2016-09-18 10:31 561 查看
在linux系统中你可能已经发现了为什么系统常常会自动的进行一些任务?这些任务到底是谁在支配他们工作的?在linux系统如果你想要让自己设计的备份程序可以自动在某个时间点开始在系统底下运行,而不需要手动来启动它,又该如何处置呢? 这些例行的工作可能又分为一次性定时工作与循环定时工作,在系统内又是哪些服务在负责?
命令at及crontab可以解决上述问题

at:未来的某时间点执行一次某任务
crontab:用于周期性运行某任务
二者的执行结果或通过邮件发送给用户。

at命令
通过命令yum provides atd查看at的包名
yum provides atd                                                                                   root@localhost
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
base/7/x86_64/filelists_db                                                                        | 6.7 MB  00:00:00
epel/x86_64/filelists_db                                                                          | 8.1 MB  00:00:00
extras/7/x86_64/filelists_db                                                                      | 391 kB  00:00:00
updates/7/x86_64/filelists_db                                                                     | 1.5 MB  00:00:00
zabbix/x86_64/filelists_db                                                                        |  53 kB  00:00:00
zabbix-non-supported/x86_64/filelists                                                             |  660 B  00:00:00
at-3.1.13-22.el7.x86_64 : Job spooling tools
Repo        : base
Matched from:
Filename    : /usr/sbin/atd
at-3.1.13-22.el7.x86_64 : Job spooling tools
Repo        : @base
Matched from:
Filename    : /usr/sbin/atd
常用格式:at [option] ... TIME
at允许使用一套相当复杂的指定时间的方法。他能够接受在当天的hh:mm(小时:分钟)式的时间指定。假如该时间已过去,那么就放在第二天执行。当然也能够使用midnight(深夜),noon(中午),teatime(饮茶时间,一般是下午4点)等比较模糊的 词语来指定时间。用户还能够采用12小时计时制,即在时间后面加上AM(上午)或PM(下午)来说明是上午还是下午。 也能够指定命令执行的具体日期,指定格式为month day(月 日)或mm/dd/yy(月/日/年)或dd.mm.yy(日.月.年)。指定的日期必须跟在指定时间的后面。 上面介绍的都是绝对计时法,其实还能够使用相对计时法,这对于安排不久就要执行的命令是很有好处的。指定格式为:now + count time-units ,now就是当前时间,time-units是时间单位,这里能够是minutes(分钟)、hours(小时)、days(天)、weeks(星期)。count是时间的数量,究竟是几天,还是几小时,等等。 更有一种计时方法就是直接使用today(今天)、tomorrow(明天)来指定完成命令的时间。

TIME:时间格式,这里可以定义出什么时候要进行 at 这项任务的时间,格式有:
HH:MM
ex> 04:00
在今日的 HH:MM 时刻进行,若该时刻已超过,则明天的 HH:MM 进行此任务。
HH:MM YYYY-MM-DD
ex> 04:00 2016-09-19
强制规定在某年某月的某一天的特殊时刻进行该项任务
HH:MM[am|pm] [Month] [Date]
ex> 04pm September 17
也是一样,强制在某年某月某日的某时刻进行该项任务
HH:MM[am|pm] + number [minutes|hours|days|weeks]
ex> now + 5 minutes
ex> 04pm + 3 days
就是说,在某个时间点再加几个时间后才进行该项任务。

常用选项
-l:查看作业队列,相当于atq
-f:从指定文件中读取作业任务,而不用再交互式输入
-d:删除指定的作业,相当于atrm
-c:查看指定作业的具体内容
-q:指明队列
注:作业执行结果是以邮件发送给提交作业的用户
在使用at命令前,我们需要先确认at所依赖的atd进程是否启用,使用命令:ps -ef | grep atd查看,若未启用则用/etc/init.d/atd start or restart开启。

执行方式:

1)交互式,在命令输入完成后使用ctrl+d保存退出;2)输入重定向3)at -f 文件

示例1:2分钟后使用ls命令展开/tmp目录(交互式命令输入结束后使用ctrl+d保存退出)
[root@docker ~]# at now + 2 minutes
at> ls /tmp
at> <EOT>
job 7 at Sun Sep 18 09:17:00 2016
命令执行结果在mail里面看
[root@docker ~]# mail
Heirloom Mail version 12.5 7/5/10.  Type ? for help.
"/var/spool/mail/root": 9 messages 1 unread
1 user@localhost.local  Tue Jul 19 16:46  90/2915  "[abrt] full crash report"
2 docker@docker.locald  Thu Sep  8 11:00  16/568   "Output from your job        1"
3 user@localhost.local  Mon Sep 12 10:31 353/15306 "[abrt] full crash report"
4 user@localhost.local  Mon Sep 12 10:31 443/17535 "[abrt] full crash report"
5 root                  Sun Sep 18 09:04  23/998   "Output from your job        3"
6 root                  Sun Sep 18 09:08  19/827   "Output from your job        4"
7 root                  Sun Sep 18 09:13 275/2986  "Output from your job        5"
8 root                  Sun Sep 18 09:15  26/552   "Output from your job        6"
>U  9 root                  Sun Sep 18 09:17  18/776   "Output from your job        7"
>U  9 root                  Sun Sep 18 09:17  18/776   "Output from your job        7"
& 9
Message  9:
From root@docker.localdomain  Sun Sep 18 09:17:01 2016
Return-Path: <root@docker.localdomain>
X-Original-To: root
Delivered-To: root@docker.localdomain
Subject: Output from your job        7
To: root@docker.localdomain
Date: Sun, 18 Sep 2016 09:17:01 +0800 (CST)
From: root@docker.localdomain (root)
Status: RO
systemd-private-2c8c4ebab1524b5c9f463bd2ec8ffea7-colord.service-gyAadP
systemd-private-2c8c4ebab1524b5c9f463bd2ec8ffea7-cups.service-6gB4MM
systemd-private-2c8c4ebab1524b5c9f463bd2ec8ffea7-rtkit-daemon.service-25oPVw
systemd-private-2c8c4ebab1524b5c9f463bd2ec8ffea7-vmtoolsd.service-sW2CqM
示例2:明天14点中,重启系统。(使用输入重定向实现)
[root@docker ~]# at 14:00 tomorrow >> time1 << eof
> reboot
> eof
job 8 at Mon Sep 19 14:00:00 2016
[root@docker ~]# atq
8Mon Sep 19 14:00:00 2016 a root
示例3:删除示例2的计划任务
[root@docker ~]# at -d 8
[root@docker ~]# atq


at命令的执行权限
配置文件/etc/at.{allow,deny}决定了允许哪些用户可以使用at命令,哪些用户不可以。

加上这两个文件后, at 的工作情况是这样的:
先找寻 /etc/at.allow 这个文件,写在这个文件中的使用者才能使用 at ,没有在这个文件中的使用者则不能使用 at (即使没有写在 at.deny 当中);
如果 /etc/at.allow 不存在,就寻找 /etc/at.deny 这个文件,若写在这个 at.deny 的使用者则不能使用 at ,而没有在这个 at.deny 文件中的使用者,就可以使用 at 命令了。
如果两个文件都不存在,那么只有 root 可以使用 at 这个命令。
透过这个说明,我们知道 /etc/at.allow 是管理较为严格的方式,而 /etc/at.deny 则较为松散 (因为帐号没有在该文件中,就能够运行 at 了)。在一般的 distributions 当中,由于假设系统上的所有用户都是可信任的, 因此系统通常会保留一个空的 /etc/at.deny 文件,意思是允许所有人使用 at 命令的意思 (您可以自行检查一下该文件)。 不过,万一你不希望有某些使用者使用 at 的话,将那个使用者的帐号写入 /etc/at.deny 即可! 一个帐号写一行。

crontab命令
通过命令yum provides crontab查看crontab命令的包名
yum provides crontab                                                                               root@localhost
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
cronie-1.4.11-17.el7.x86_64 : Cron daemon for executing programs at set times
Repo        : base
Matched from:
Filename    : /usr/bin/crontab
cronie-1.4.11-14.el7_2.1.x86_64 : Cron daemon for executing programs at set times
Repo        : @anaconda
Matched from:
Filename    : /usr/bin/crontab


cron来源于希腊单词chronos(意为“时间”),是linux系统下一个周期性自动执行指定任务的程序
在使用cron前,需要确认crond守护进程处于运行状态,才能保证cron的正常运行。
可以通过命令:systemctl status crond 及ps -ef | grep crond查看服务cron是否处于运行状态。

向crond提交作业的方式与at不同,它需要使用专用的配置文件,此文件有固定格式,不建议使用文本编辑器直接编辑此文件;需要使用crontab命令;
cron任务分为两类:
系统cron任务:主要用于实现系统自身的维护
手动编辑/etc/crontab文件
用户cron任务:使用命令crontab

/etc/crontab文件




1)每一行定义一个周期性任务;共7个字段
* * * * * :定义周期性时间
username:运行任务的用户身份
command to be executed:要执行的任务
2)此处的环境变量不同于用户登陆后获得的环境,因此建议命令使用绝对路径,或定义PATH环境变量
3)执行结果邮件发送给MAILTO指定的用户(发送给运行任务的用户)

时间表示法
(1) 特定值
给定时间点有效取值范围内的值;
(2) *
给定时间点上有效取值范围内的所有值;
表示“每...”;
示例:
1> 3 * * * * :每小时的第三分钟执行一次
2> 3 4 * * 5 :每周的周五4:03执行一次
3> 5 6 7 * * :每月的7号6:05执行一次
4> 7 8 9 10 * :每年10月9号8点7分执行一次
(3) 离散取值:在时间上使用逗号分隔的多个值:#,#,#
示例:
5> 9 8 * * 3,7 :每周三周日的8点9分执行一次
6> 0 8,20 * * 3,7 :每周三周日的8:00跟20:00执行一次
(4) 连续取值:在时间点上使用-链接开头和结束:#-#
示例:
7> 0 9-18 * * 1-5 :从周一到周五的9点到18点每小时执行一次
(5) 在指定时间范围上,定义步长
/#: #即为步长
注:1)指定时间点不能被步长整除时,其意义将不复存在:
2)最小时间单位为“分钟”,想完成“秒”级任务,需要借助于其他机制:定义成每分钟任务,而在利用脚本实现的每分钟之内循环多次

用户cron
crontab命令定义,每个用户都有专用的cron任务文件:/var/spool/cron/USERNAME
只有该用户定义了cron任务才能通过该文件看到相应信息。
注:1)每行定义一个cron任务,共6个字段(不需要指定用户);2)邮件发送给当前用户
crontab命令
使用格式:
crontab [-u user] [-l | -r | -e] [-i]
-l: 列出所有任务;
-e: 编辑任务;
-r: 移除所有任务;
-i:同-r一同使用,以交互式模式让用户有选择地移除指定任务;

-u user: 仅root可运行,代为为指定用户管理cron任务;

注意:运行结果以邮件通知给相关用户;如果不想接收邮件则可使用如下命令实现
(1) COMMAND > /dev/null
(2) COMMAND &> /dev/null

思考:
(1) 如何在秒级别运行任务?
* * * * * for min in 0 1 2; do echo "hi"; sleep 20; done
(2) 如何实现每7分钟运行一次任务?

sleep命令:
sleep NUMBER[SUFFIX]...

SUFFIX:
s: 秒, 默认
m: 分
h: 小时
d: 天

练习:
1、每4小时备份一次/etc目录至/backup目录中,保存的文件名称格式为“etc-yyyy-mm-dd-HH.tar.xz”;
在/etc/crontab文件中添加如下:

0 4 * * * ./test/bak_etc
cat bak_etc
#!/bin/bash
#bakup /etc diratory
#auther chawan date:20160908
cp /etc/* /bakup/etc$(date +%F-%H)
xz /bakup/etc$(date +%F-%H)


2、每周2, 4, 7备份/var/log/messages文件至/logs目录中,文件名形如“messages-yyyymmdd”;
* * * * 2,4,7 ./test/logs

cat /test/logs
#!/bin/bash
#bakup /var/log/messages to /logs
cp /var/log/messages /logs/messages$(date +%F)
xz /logs/messages$(date +%F)


3、每两小时取出当前系统/proc/meminfo文件中以S或M开头的信息追加至/tmp/meminfo.txt文件中;
0 2 * * * cat /proc/meminfo | grep "^[SM]" >> /tmp/meminfo.txt


4、工作日时间内,对用户docker每小执行一次“ip addr show”命令;
切换至docker用户使用命令crontab -e进入编辑界面
加入"0 9-18 * * 1-5 docker ip addr show"信息后保存退出
[docker@docker ~]$ crontab -l
0 9-18 * * 1-5 ip addr show
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  at;cron