重定向

此博客已停止更新,新址: http://blog.scicooking.net


2008年11月14日星期五

Crontab 详解

主要信息来源于 info crontab

crontab 要做的事就是:“在指定日期指定时间运行指定的命令”。每个用户都有自己的 crontab, crontab 里的每个命令都以 crontab 拥有者的身份运行。

空行、前导空格和制表符(tab)都会被忽略。 首个非空白字符是 # 的行是注释。注意:和命令同一行的 # 不会当作注释,会当成命令的一部分。在设置环境变量的行也是同样的。也就是说,注释是单独成行的

crontab 里有效的行可以是 设置环境变量 或者 cron 命令。环境变量设置类似于: name = value “=” 两边的空格可选(这点和 bash 不同, bash 中变量赋值=号两边不能有空格)。如果想要在值中保留前后空格,可以用单引号或者双引号包含起来。注意,这里设置的值不会被环境解析和替代,也就是所谓变量不会被展开。比如:PATH = $HOME/bin:$PATH 不会像预期一样工作。

cron 守护进程只设置了少数几个环境变量。 SHELL 设置为 /bin/sh, LOGNAME 和 HOME 设置为 用户相关的目录 (来自 /etc/passwd 相关的信息), PATH 设置为 “/usr/bin:/bin“。 HOME, SHELL, PATH 可以在 crontab 中重新设置,LOGNAME 是 job 运行的用户, 无法被改变。
(注: LOGNAME 在 BSD 系统上叫做 USER, 其他系统上 也设置了 USER 变量)

除了 LOGNAME, HOME 和 SHELL, 如果在当前的 crontab 中因为任何原因要发送命令运行结果的邮件, cron 会查找 MAILTO 这个变量. 如果定义了 MAILTO 变量(并且非空),邮件就会发送给这个用户。MAILTO 可以指定多个接收人,用逗号 "," 分隔。如果 MAILTO 定义成空 (MAILTO=""),将不会发送任何邮件。否则邮件将发送给 crontab 所属的用户。
特性:如果 crontab 中的命令有任何输出结果,cron 就会发送邮件把输出发送给用户,如果 MAILTO="" 将关闭这个特性不会发送邮件。

默认情况下, cron 发送邮件使用的 "Content-Type:" 邮件头是"text/plain", 并带有"charset=" 参数来设置到 crond 启动所在的区域字符集。比如,LC_* 环境变量指定的区域 或者 如果没有 LC_* 环境变量就使用默认系统区域。你可以为发送到 mail 的 cron job 的输出使用不同的字符编码,通过在 crontab 中设置 CONTENT_TYPE 和 CONTENT_TRANSFER_ENCODING 变量为正确的 mail 头信息。

------------ 小节分割线 ---------------

cron 命令格式是非常的 V7 标准 - -; 也带有向前兼容的数字扩展。每行有 5 个时间和日期字段,跟着是命令,然后是换行("\n")。系统级的 crontab (/etc/crontab) 使用相同格式, 除了在时间日期之后,命令之前指定了一个用于执行命令的用户名。字段可以用一个或者多个空格或者tab分隔。

当分钟、小时和月份匹配当前时间,并且两个天的字段(几号或者星期几)中至少一个匹配当前时间(看下面的注释!), cron 就开始执行命令. cron 每分钟都检查一次。时间和日期的字段:

字段 允许的值
---- --------
分钟 0-59
小时 0-23
日 1-31
月 1-12 (或者英文名称)
星期 0-7 (0 和 7 都是星期天,或者使用英文名称)

字段可以使用星号(*),总是代表“first-last”,也就是所有的值。

允许数字范围。范围就是2个数字之间用连字号(-)连接, 包括这两个数字。 比如, 小时字段 8-11 表示在 8, 9, 10 和 11 点执行。

也允许列表。列表是一组数字(或者范围),由逗号(,)分隔。比如 “1,2,5,9”, “0-4,8-12”。

步进值可以和范围结合。在范围后跟着“/数字”指定从范围中跳过指定数字。比如,小时字段“0-23/2”可以用来指定每几小时执行(V7 标准另一写法是 “0,2,4,6,8,10,12,14,16,18,20,22”)。步进当然也允许跟在星号后,所以如果你想要的是“每2小时”,直接用“*/2”就可以了。

月份和星期可以使用英文名称。使用星期或者月份的前3个字母的缩写(无论大小写)。不能在范围或者列表中使用英文名称。

第6个字段(也就是这一行的剩余部分)就是指定要运行的命令了。整个命令部分,到换行(\n)或者 % 字符,会交给 /bin/sh 或者 crontab 文件里 SHELL 变量指定的 shell 来执行。命令中的百分号(%),除了加上反斜杠(\)转义的,会被转为换行符,并且第一个 % 之后的所有数据都会发送给命令当作标准输入。这里没办法像 shell 跟着 "\" 一样把命令写成多行的。

注意:
命令执行的天可以由2个字段来指定 -- 几号和星期几。如果2个都有限制(不是 *),那么只要其中一个匹配当前时间命令就会执行。比如:“30 4 1,15 * 5” 会导致命令在每月1号和15号加上每个星期五运行。

以下 8 个特殊的字符串可以替代开头的 5 个字段:

字符串 含义
------ ----
@reboot 启动时运行一次
@yearly 每年运行一次,“0 0 1 1 *”
@annually (同 @yearly)
@monthly 每月运行一次,“0 0 1 * *”
@weekly 每周运行一次,“0 0 * * 0”
@daily 每天运行一次,“0 0 * * *”
@midnight (同 @daily)
@hourly 每小时运行一次,“0 * * * *”


例子:

# 使用 /bin/bash 来运行命令, 替代默认的 /bin/sh
SHELL=/bin/bash
# 设定发送运行结果给 “ken”, 而不管这个 crontab 是谁的
MAILTO=ken
#
# 每天 00:05 运行,输出重定向到 用户目录的下的 tmp/out 文件,错误也重定向到这个文件
5 0 * * * $HOME/bin/daily.job >> $HOME/tmp/out 2>&1
# 每月 1 号的 14:15 -- 输出发送给 ken(上面 MAILTO 指定的接收者)
15 14 1 * * $HOME/bin/monthly
# 每个工作日 22:00 运行, 这条命令就是定时发邮件,骚扰 Rock, %都会变成换行,第一个 % 后的数据都作为标准输入给 mail
0 22 * * 1-5 mail -s "It's 10pm" rock%Rock,%%Where are your kids?%
# 每天每2小时在23分时运行
23 0-23/2 * * * echo "run 23 minutes after midn, 2am, 4am ..., everyday"
# 每周日 04:05 运行
5 4 * * sun echo "run at 5 after 4 every sunday"


再说几句总结:
  • 指定星期时, 0 和 7 都会被当作星期天。 BSD 和 ATT 貌似不这么认为。
  • 列表和范围可以在同一个字段并存。 但是“1-3,7-9”会被 ATT 或 BSD cron 拒绝 -- 他们只想看到 “1-3” 或者 “7,8,9”。
  • 范围可以包括步进,因此 “1-9/2” 等同于 “1,3,5,7,9”。
  • 月份和星期可以用名称。
  • 可以在 crontab 中设置环境变量。 BSD 或 ATT 中,交给子进程的环境变量来基本来自 /etc/rc。
  • 命令的输出发送给 crontab 的拥有者(BSD不会这么做),可以发送给其他人(SysV 不能这么干),或者可以关闭这个特性根本不发送邮件(SysV 还是不能这么干)。
  • 所有出现在前面 5 个字段位置 @ 命令是扩展。
---- 到此结束的分割线 ----

看到这里说明你很有耐心很想了解 crontab 设置……以上就那么多, 转载请注明来源,谢谢!

没有评论: