9.7. 使用 cron 和 atd运行计划任务
cron
是负责调度和运行周期命令(每天,每周,等)的守护进程; atd
用于处理单次执行命令,命令将在未来某个指定时刻运行。
在Unix 系统,许多任务都被周期性的调度:
更新日志;
更新
locate
程序数据库;备份;
维护脚本(例如清理临时文件)。
默认情况下,所有用户都可以运行计划任务。每个用户有他们自己的 crontab 其中记录了要调度的命令。可以运行 crontab -e
编辑(其内容存储在 /var/spool/cron/crontabs/*user*
文件中)。
安全 限制 cron
或者 atd
可以通过创建排他性的授权文件 /etc/cron.allow
来限制对 cron
的访问,其中指明仅那些用户有权调度。而其他用户则自动被剥夺权限。相反,想仅阻止一两个问题用户,可以将其写入禁止文件(黑名单),/etc/cron.deny
。 atd
也具有相同的特性,对应文件 /etc/at.allow
和 /etc/at.deny
。
超级用户有自己的 crontab,但是也可以使用 /etc/crontab
文件,或者在 /etc/cron.d
目录中写入另外的crontab 文件。这两种方法可以用来指明执行命令时的用户身份。
cron 软件包默认包含一些可执行的调度命令:
每小时运行在
/etc/cron.hourly/
文件夹内的程序;每天运行在
/etc/cron.daily/
文件夹内的程序;每周运行在
/etc/cron.weekly/
文件夹内的程序;每月运行在
/etc/cron.monthly/
文件夹内的程序。
很多 Debian 软件包依赖此服务:把维护脚本置于此文件夹,确保其服务的最佳运作。
9.7.1. crontab 文件的格式
提示 cron
中的快捷方式
cron
可以识别一些简写名称用以表示在 crontab
中开头的五个时间区段。他们对应最常用的调度选项:
@yearly
:每年一次(一月一号,00:00);@monthly
:每月一次(每月一号,00:00);@weekly
:每周一次(周日00:00);@daily
:每天一次(在00:00);@hourly
:每小时一次(在每小时开始)。
特例 cron
和日光节约时间
在Debian中, cron
尽量考虑时间变更(夏令时,或者本地时间的重大变化)。因此,被安排到不存在时间(例如,安排在法国春季时间2:30执行的任务,而时钟在凌晨2:00之后会直接跳到凌晨3:00)的命令会在时间改变后马上执行(大概在夏令时3:00)。另一方面,在秋天,需要多次执行的命令(夏令时凌晨2:30,标准时间凌晨2:30之后一个小时,由于凌晨在3:00,时钟被回调至凌晨2:00)只会执行一次。
要当心了,如果不同任务的调度顺序和延迟相互关联,就需要检查使用 cron
时,是否兼容一致;如果有必要,为每年可能发生问题的夜晚准备专门的调度程序。
crontab 每列以六个 (或七个) 字段描述排定的命令:
分钟值(从0到59);
小时(从0到23);
每月的日期值(从1到31);
月份值(从1到12);
星期值(从0到7,1对应星期一,0和7都代表星期日;也可以使用星期英文表示单次的前三个字母,例如
Sun
,Mon
,等);命令将以哪个用户的名义执行(在文件
/etc/crontab
和/etc/cron.d/
中,而不是在用户自己的调度文件中);要执行的命令(当满足前面5栏定义的条件时)。
全部的细节记录在 crontab(5) 手册中。
每个值可以表示为所有可能值的列表(使用逗号分隔)。语法a-b
描述介于 a
和 b
中间的所有值。语法 a-b/c
描述以c
为增量间隔(例如: 0-10/2
代表 0,2,4,6,8,10
)。星号 *
是通配符,代表所有可能值。
例 9.2. 示例 crontab
文件
- #格式
- #分钟 小时 天 月份 星期 命令
- # 每天晚上七点二十五分下载数据
- 25 19 * * * $HOME/bin/get.pl
- # 周内每天早上八点(周一至周五)
- 00 08 * * 1-5 $HOME/bin/dosomething
- # 每次重启后启动 IRC 代理
- @reboot /usr/bin/dircproxy
提示 在启动时运行命令
只是在系统启动后,单次执行一个命令,可以使用 @reboot
宏(仅仅重启 cron
命令不会触发使用@reboot
调度的命令)。该宏表示了 crontab条目的前五个区段。
其他 仿真 cron
用 systemd
It is possible to emulate part of cron
‘s behavior with systemd
‘s timer mechanism (see 第 9.1.1 节 “Systemd 启动系统”).
9.7.2. 使用 at 命令
at
在未来的特定时间运行某个命令。以命令行参数的模式在指定的时间与日期运行,并把结果以标准方式键入。键入当前的 shell 就可以运行该命令。at
甚至保留当前的环境,以便重现运行该命令的情境。以惯例显示时间:16:12
或 4:12pm
代表下午 4 点 12 分。日期可以使用欧洲或西方的格式,包括 DD.MM.YY
(27.07.15
表示27日7月2015年),YYYY-MM-DD
(等同于 2015-07-27
),MM/DD/[CC]YY
(就是,12/25/15
或 12/25/2015
指的是12月25日,2015),或 MMDD[CC]YY
(即 122515
或 12252015
代表12月25日,2015)。少了它,则在时间到就运行 (同一天、或若时间已过则是隔天)。也可写成 “today” 或 “tomorrow”,就是今天或明天。
$
另外一种方法可以向后推迟一段时间执行命令:at now + *数字* *间隔*
。 间隔 可以是 分钟
, 小时
, 天
, 或者 星期
。 数字 指明在命令执行之前消逝时间的单位数量。
要取消 cron
中的计划任务,运行 crontab -e
删除 crontab 文件中的对应行。对于使用 at
命令的任务,同样简单:运行 atrm *任务编号*
。任务编号在调度时有 at
命令指定,可以通过 atq
命令查询找到,该命令给出当前计划任务清单。