九里大集

Eternachen's Blog

Linux计划任务(at batch crontab anacron)

声明:以下blog转载自旷世的忧伤 Huoty’s Blog,一切权利归原作者所有。

at在未来只做一次任务调度,依赖于atd 服务;batch 命令被用来在系统平均负载达到 0.8% 以下时执行一次性的任务;cron 在未来周期性的执行任务,依赖于 crond 服务;anacron 用于在开机时执行上次停机时没有完成的 crontab 任务,依赖于anacron服务。

at

Ubuntu系统需要手动安装:

apt-get install at

at 命令被用来在指定时间内调度一次性的任务。命令格式如下:

at [-mldv] TIME

选项与参数:

-m :当at的任务完成后,即使没有输出信息,也以 email 通知给使用者
-l :列出目前系统上面的所有该使用者的at任务(同atq)
-d :可以取消一个在 at 任务(同atrm)
-v :可以使用较明显的时间格式列出 at 任务
-c :可以列出后面接的该项任务的内容
-I : atq的别名
-V : 显示版本信息
-q<列队> : 使用指定的列队
-f<文件> : 从指定文件读入任务而不是从标准输入读入
-t<时间参数> : 以时间参数的形式提交要运行的任务

at命令的时间格式:

now + 时间: 时间以 minutes、hours、days、或 weeks 为单位
HH:MM: 24小时制度,如果时间已过,就会在第二天的这一时间执行
midnight: 表示00:00
noon: 表示12:00
teatime: 表示16:00

示例:

[root@localhost ~]# at 17:20 tomorrow
at> date >/root/2013.log
at> <EOT>
job 8 at 2013-01-06 17:20

batch

batch 命令被用来在系统平均负载达到 0.8% 以下时执行一次性的任务,通俗的所就是系统空闲时执行任务。用法与at一样 。

需要注意的是, /etc/at.allow/etc/at.deny 文件可用来限制对 at 和 batch 命令的使用(root用户不受其控制)。这两个使用控制文件的格式都是每行一个用户(不允许空格),且文件修改后,atd守护进程不需重启。如果at.allow文件存在,那么只有其中列出的用户才被允许使用at或batch命令,且忽略cron.deny文件。如果at.allow文件不存在,那么所有在cron.deny中列出的用户都将禁止使用at和batch.。

crontab

Crontab 用于定时的执行某项任务,其运行通过 cron 守护进程来完成,进程每分钟会定期检查是否有要执行的任务。

cron 服务通过 crontab 命令来设定具体的周期性任务,我们可以在固定的间隔时间执行指定的系统指令或一些脚本。时间间隔的单位可以是分钟、小时、日、月、周及以上的任意组合。这个命令对于需要周期性运行的程序是非常有用的。

命令格式:

crontab [-u user] file

crontab [ -u user ] [ -i ] { -e -l -r }

参数说明:

  • -u user:用来设定某个用户的crontab服务;
  • file:file 是命令文件的名字,表示将 file 做为 crontab 的任务列表文件并载入 crontab。如果在命令行中没有指定这个文件,crontab 命令将接受标准输入(键盘)上键入的命令,并将它们载入 crontab。
  • -e:编辑某个用户的 crontab 文件内容。如果不指定用户,则表示编辑当前用户的 crontab 文件。
  • -l:显示某个用户的 crontab 文件内容,如果不指定用户,则表示显示当前用户的 crontab 文件内容。
  • -r:从 /var/spool/cron 目录中删除某个用户的 crontab 文件,如果不指定用户,则默认删除当前用户的 crontab 文件。
  • -i:在删除用户的 crontab 文件时给确认提示。

需要注意的是,Linux 下的 cron 任务调度分为两类:系统任务调度和用户任务调度。

系统任务

系统周期性所要执行的工作,比如写缓存数据到硬盘、日志清理等。在/etc目录下有一个crontab文件,这个就是系统任务调度的配置文件。 /etc/crontab 文件包括下面几行:

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user	command
17 *	* * *	root    cd / && run-parts --report /etc/cron.hourly
25 6	* * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6	* * 7	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6	1 * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#

crontab 的文件格式:

  • 第1列 分钟0~59
  • 第2列 小时0~23(0表示子夜)
  • 第3列 日1~31
  • 第4列 月1~12
  • 第5列 星期0~6(0表示星期天)
  • 第6列 运行命令的用户
  • 第7列 要运行的命令

时间配置的特殊字符:

  • 星号( * ):代表所有可能的值,例如month字段如果是星号,则表示在满足其它字段的制约条件后每月都执行该命令操作。
  • 逗号( , ):可以用逗号隔开的值指定一个列表范围,例如,“1,2,5,7,8,9”
  • 中杠( - ):可以用整数之间的中杠表示一个整数范围,例如“2-6”表示“2,3,4,5,6”
  • 正斜线( / ):可以用正斜线指定时间的间隔频率,例如“0-23/2”表示每两小时执行一次。同时正斜线可以和星号一起使用,例如*/10,如果用在minute字段,表示每十分钟执行一次。

实际上,一般不建议直接修改 /etc/crontab 文件,而是在 /etc/cron.d 目录下创建额外的配置,该目录下的配置文件格式与 /etc/crontab 相同。但需要注意的是,此目录下的文件有命名规则,文件名由大小写字母,数字,横杠和下划线组成,不能包括圆点, 且文件所有者必须是 root:root,文件权限必须是 644(-rw-r–r–),为软链接时,链接的文件所有者也必须是 root

用户任务

用户定期要执行的工作,比如用户数据备份、定时邮件提醒等。用户可以使用 crontab 工具来定制自己的计划任务。所有用户定义的 crontab 件都被保存在 /var/spool/cron 目录中,用户任务的配置文件中不需要指定运行用户字段。其文件名与用户名一致,使用者权限文件如下:

  • /etc/cron.deny 该文件中所列用户不允许使用 crontab 命令
  • /etc/cron.allow 该文件中所列用户允许使用 crontab 命令
  • /var/spool/cron/ 所有用户 crontab 文件存放的目录,以用户名命名

可以用 crontab -e 来编辑用户任务,EDITOR 环境变量可以用来指定编辑器,例如设置编辑器为 vim:

export EDITOR=vim;

笔记: 在 vim 下如果要查看当前文件所在路径,可以先按下数字1,然后按下组合键 CTRL + G,这样可以看到当前编辑的 crontab 文件其实是一个临时文件。

一些配置示例:

# 每 1 分钟执行一次 command
* * * * * command

# 每小时的第 3 和第 15 分钟执行
3,15 * * * * command

# 在上午 8 点到 11 点的第 3 和第 15 分钟执行
3,15 8-11 * * * command

# 每隔两天的上午 8 点到 11 点的第 3 和第 15 分钟执行
3,15 8-11 */2  *  * command

# 每周一上午 8 点到 11 点的第 3 和第 15 分钟执行
3,15 8-11 * * 1 command

# 每月 1、10、22 日的 04:45 重启 nginx
45 4 1,10,22 * * sudo service nginx restart

# 每周六、周日的 01:10 重启 nginx
10 1 * * 6,0 sudo service nginx restart

经验总结

系统级任务配置

系统级任务调度主要完成系统的一些维护操作,用户级任务调度主要完成用户自定义的一些任务,可以将用户级任务调度放到系统级任务调度来完成(不建议这么做),但是反过来却不行。root 用户的任务调度操作可以通过 crontab -u root –e 来设置,也可以将调度任务直接写入 /etc/crontab 文件。需要注意的是,如果要定义一个定时重启系统的任务,就必须将任务放到 /etc/crontab 文件,即使在 root 用户下创建一个定时重启系统的任务也是无效的。

重定向输出

每条任务调度执行完毕,系统都会将任务输出信息通过电子邮件的形式发送给当前系统用户,这样日积月累,日志信息会非常大,可能会影响系统的正常运行,因此,将每条任务进行重定向处理非常重要。 例如,可以在 crontab 文件中设置如下形式,忽略日志输出:

0 */3 * * * /usr/local/apache2/apachectl restart >/dev/null 2>&1

/dev/null 2>&1 表示先将标准输出重定向到 /dev/null,然后将标准错误重定向到标准输出,&1 表示文件描述符 1。由于标准输出已经重定向到了 /dev/null,因此标准错误也会重定向到 /dev/null,这样日志输出问题就解决了。

或者将输出定向到文件,以便于在出错时定为问题:

* * * * * command >>/tmp/command.log 2>>command.err

无法同时指定月和星期

另一个需要注意的地方在于,你可以分别以周或者是日月为单位作为循环,但你不可使用 几月几号且为星期几 的模式工作,也就是说周与日月不可同时并存。

设置秒级任务

如果要设置秒级别的任务,可以通过 sleep 命令来完成,例如 30 秒执行一次 rm -rf /tmp/*

* * * * * rm -rf /tmp/*
* * * * * sleep 30; rm -rf /tmp/*

单独记录 cron 日志

在 Ubuntu 系统上,cron 的日志默认输出到 syslog 中,如果需要将 cron 日志输出到独立的文件中,则应修改 /etc/rsyslog.d/50-default.conf 文件,注释掉如下行的内容:

#cron.*              /var/log/cron.log

然后重启 rsyslog 和 cron 服务:

sudo service rsyslog  restart
sudo service cron restart

在 cron 配置中定义变量

在 crontab 的配置中支持引用环境变量,也支持定义变量,但切记 不能在变量定义时引用其他变量,如 B=$A 这样定义时是无效的,变量 A 不会展开,所以 B 的值直接是 $A。这一点与 /etc/environment 文件的配置类似。

使用 % 需要转义

在 crontab 中 % 是有特殊含义的,其表示需要换行。所以在使用 % 时需要用反斜杠转义,如在格式化日志时用 date +%Y%m%d 在 crontab 中不会得到执行,应使用 date +\%Y\%m\%d 代替。

在 /etc/cron.d 中的配置文件有格式要求

如果需要把 cron 的定时任务配置放荡 /etc/cron.d 目录中,则需注意该目录下的文件有一定格式要求,其文件名由大小写字母,数字,横杠和下划线组成,特别要注意不能包括圆点, 且文件所有者必须是 root:root,文件权限必须是 644(-rw-r–r–),为软链接时,链接的文件所有者也必须是 root 账户。最好是编写一个脚本来部署该目录下的配置文件,如:

# deploy cron config file to /etc/cron.d

set -e

for path in $@; do
    dst_path=/etc/cron.d/$(basename $path)
    if [ -f $dst_path ]; then
        mv -v $dst_path ${dst_path}.$(date +"%Y%m%d%H%M%S")
    fi
    cp -v $path /etc/cron.d
    chown -v root:root $dst_path
    chmod -v 644 $dst_path
    md5sum $path
    md5sum $dst_path
    ls -l $dst_path
done

exit 0

anacron

cron 是用来控制循环执行的例行性工作的,可循环的时间为分钟、小时、每周、每月或每年等。比如我要设定机器每天早上8点进行备份,就可以用到这个服务。除非我们的机器保持每天都24小时开始,否则就会有些系统例行工作都没有人做了,这个时候就可以用到 anacron 了。

anacron 并不是用来取代 cron 的,anacron 存在的目的就在于我们上面提到的,在处理非 24 小时一直启动的 Linux 系统的 cron 服务的执行!所以 anacron 并不能指定何时执行某项任务, 而是以天为单位或者是在开机后立刻进行 anacron 的动作,他会去侦测停机期间应该进行但是并没有进行的 cron 服务,如果有就将该任务执行一遍,然后就自动停止。

anacron会以一天、七天、一个月周期去侦测系统中未进行的crontab任务,因此对于某些特殊的使用环境非常有帮助。anacron 会去会去分析现在的时间与时间记录档所记载的上次运行 anacron 的时间,两者比较厚若发现有差异,也就是在某些时刻没有进行crontab,那么此时anacron就会开始执行未运行的 crontab 了。所以 anacron 也是听过 crontab 来运行的,因此 anacron 运行的时间通常由两个,一个是系统启动期间运行,一个是写入 crontab 的排程中,这样才能够在特定时间分析系统未进行的 crontab 工作。我们可以使用 ll /etc/cron*/*ana* 的方式来查看 anacron 的侦测时间。但是我们仔细分析该文件的话,发现它主要是执行 anacron 命令。

anacron命令的语法如下:

  • (1) -s 开始连续的运行各项工作,会一句时间记录当的数据判断是否进行。
  • (2) -f 强制进行,而不去判断时间登录档的时间戳。
  • (3) -n 立即进行未进行的任务,而不延迟等待时间。
  • (4) -u 仅升级时间记录当的时间戳,不进行任何工作。

而 anacron 的配置文件是 /etc/anacrontab,而它的很多内容则是在 /var/spool/anacron 里面保存。当 anacron 下达 anacron -s cron.daily 时,它会有如下的步骤:

  • (1) 由 /etc/anacrontab 分析到 cron.daily 这项工作名称的天数为一天。
  • (2) 由 /var/spool/anacron/cron.daily 取出最近一次运行anacron的时间戳。
  • (3) 把取出的时间戳与当前的时间戳相比较,如果差异超过了一天,那么就准备进行命令。
  • (4) 若准备进行命令,根据 /etc/anacrontab 的配置,将延迟 65m分钟。
  • (5) 延迟时间后,开始运行后续命令,也就是 run-parts /etc/cron.daily 这串命令。
  • (6) 运行完毕后,anacron 程序结束。
Top