一、Crontab介绍
crontab命令的功能是在一定的时间间隔调度一些命令的执行。
1.1 /etc/Crontab文件
在/etc目录下有一个crontab文件,这里存放有系统运行的一些调度程序。每个用户可以建立自己的调度crontab(在/var/spool/cron目录下)。
以下是我本机上的crontab文件,
[root@localhost etc]# cat /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/
# run-parts
01 * * * * root run-parts /etc/cron.hourly
02 4 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly
二、Crontab使用说明
2.1 Crontab基本语法
usage: crontab [-u user] file
crontab [-u user] [ -e | -l | -r ]
(default operation is replace, per 1003.2)
-e (edit user's crontab)
-l (list user's crontab)
-r (delete user's crontab)
-i (prompt before deleting user's crontab)
-s (selinux context)
其中,file是命令文件的名字。如果在命令行中指定了这个文件,那么执行crontab命令,则将这个文件拷贝到crontabs目录下;如果在命令行中没有制定这个文件,crontab命令将接受标准输入(键盘)上键入的命令,并将他们也存放在crontab目录下。
如果想查看Crontab更详细的语法及使用帮助,则可以通过man crontab来查看帮助。
2.2 Crontab 格式说明
我们可以用crontab -e 添加要执行的命令。 命令执行的结果,无论是标准输出还是错误输出,都将以邮件形式发给用户。
添加的命令必须以如下格式:
* * * * * /需执行命令的路径
前五个字段可以取整数值,指定何时开始工作,第六个域是字符串,即命令字段,其中包括了crontab调度执行的命令。 各个字段之间用spaces和tabs分割。
前5个字段分别表示:
分钟:0-59
小时:1-23
日期:1-31
月份:1-12
星期:0-6(0表示周日)
还可以用一些特殊符号:
*: 表示任何时刻
,: 表示分割
-:表示一个段,如第二端里: 1-5,就表示1到5点
/n : 表示每个n的单位执行一次,如第二段里,*/1, 就表示每隔1个小时执行一次命令。也可以写成1-23/1.
一些示例:
00 8,12,16 * * * /test/command.sh
30 2 * * * /test/command.sh
10 8,12,16 * * * /test/command.sh
10 8,12,16 * * * /test/command.sh
10 8,12,16 * * * /test/command.sh
43 21 * * * 21:43 执行
15 05 * * * 05:15 执行
0 17 * * * 17:00 执行
0 17 * * 1 每周一的 17:00 执行
0,10 17 * * 0,2,3 每周日,周二,周三的 17:00和 17:10 执行
0-10 17 1 * * 毎月1日从 17:00到17:10 毎隔1分钟 执行
0 0 1,15 * 1 毎月1日和 15日和周一的 0:00 执行
42 4 1 * * 毎月1日的 4:42分 执行
0 21 * * 1-6 周一到周六 21:00 执行
0,10,20,30,40,50 * * * * 每隔10分 执行
*/10 * * * * 每隔10分 执行
* 1 * * * 从1:0到1:59 每隔1分钟 执行
0 1 * * * 1:00 执行
0 */1 * * * 毎时0分 每隔1小时 执行
0 * * * * 毎时0分 每隔1小时 执行
2 8-20/3 * * * 8:02,11:02,14:02,17:02,20:02 执行
30 5 1,15 * * 1日和15日的5:30 执行
有一个字符串由多个变量拼接而成: "$x1$x2$x3$x4$x5$x6..." ,这个列表可以一直延伸到 $x10000,而每个变量都至少有一种可能的取值,为了简化问题,每个变量不会再引用别的变量。
现在,给定一个字符串T,判断这个字符串是否能由上面这个 "$x1$x2$x3$x4$x5$x6..." 生成。
分析我们可以算出,总的可能性(最多)是 n1*n2*n3*n4*n5*n6...。
最笨的办法因为现实中不会有太极端的情况,我们可以将这些字符串全部扩展出来,放入一个hash table。但是,如何得到这些扩展结果呢?
这是一个笛卡尔积的问题,可以用最简单的数数的方法,先从最低位数,数到最大值时,进一位,低位置零,直到最高位也达到最大:
// radix[i] 表示第 i 位的进制 // digits 数组是输出,长度也是 len // 开始调用该函数时要将 digits 清零 bool next(const int* radix, int len, int* digits) { for (int i = len-1; i >= 0; --i) { assert(radix[i] > 0); assert(digits[i] < radix[i]); if (++digits[i] == radix[i]) digits[i] = 0; else return true; // 下一个数字 } return false; // 已结束,数字数完了 }
当然这个问题还有别的解法,例如用直接的树的深度优先遍历法。不过 next 函数本质上就是一个树深度优先遍历的 iterator。每次得到一个digits,就可以拼接字符串了:
str = ""; for (int i = 0; i < len; ++i) str += x[i][digits[i]];正则表达式 对正则表达式熟悉的朋友可能一开始就想到了:"(x11|x12|x13...)(x21|x22|x23...)(x31|x32|x33...)..."
这个方法比hash table 好一点,现实中这种办法用起来也很快捷。但是,如果$x1 有 1,000,000 种可能,$2 到 $6 都只有 1 种可能,现存的任何一个正则表达式引擎都会爆掉!
使用自动机第13章 IGMP:Internet组管理协议
13.1 引言
12.4节概述了 IP多播给出,并介绍了 D类IP地址到以太网地址的映射方式。也简要说明了 在单个物理网络中的多播过程,但当涉及多个网络并且多播数据必须通过路由器转发时,情况会复杂得多。
本章将介绍用于支持主机和路由器进行多播的 Internet 组管理协议( IGMP)。它让一个物理网络上的所 有系统知道主机当前所在的多播组。多播路由器需要这 些信息以便知道多播数据报应该向哪些接口转发。 IGMP 在RFC 1112中定义 [Deering 1989]。
正如 I C M P 一样, I G M P 也被当作 I P 层的一部分。
IP数据报
IP首部 IGMP报文
20字节 8字节
图13-1 IGMP报文封装在IP数据报中
IGMP报文通过 IP数据报进行传输。不像我们已经见到的其他协议, IGMP有固定的报文长度, 没有可选数据。图 13-1显示了 IGMP报文如何封装在 IP数据报中。
IGMP报文通过 IP首部中协议字段值为 2来指明。
13.2 IGMP报文
图13-2显示了长度为 8字节的 IGMP报文格式。
4位
IGMP
版本(1)
4位
IGMP
类型(1-2)
未用 检验和
32位组地址(D类IP地址)
8字节
图13-2 IGMP报文的字段格式
这是版本为 1的IGMP。IGMP类型为 1说明是由多播路由器发出的查询报文,为 2说明是主 机发出的报告报文。检验和的计算和 ICMP协议相同。
组地址为 D类IP地址。在查询报文中组地址设置为 0,在报告报文中组地址为要参加的组 地址。在下一节中,当介绍 IGMP如何操作时,我们将会更详细地了解它们。
13.3 IGMP 协议
13.3.1 加入一个多播组
多播的基础就是一个进程的概念(使用的术语进程是指操作系统执行的一个程序),该进 程在一个主机的给定接口上加入了一个多播组。在一个给定接口上的多播组中的成员是动态
的—它随时因进程加入和离开多播组而变化。
这里所指的进程必须以某种方式在给定的接口上加入某个多播组。进程也能离开先前加 入的多播组。这些是一个支持多播主机中任何 API所必需的部分。使用限定词“接口”是因为 多播组中的成员是与接口相关联的。一个进程可以在多个接口上加入同一多播组。
Stanford大学伯克利版Unix中的IP 多播详细说明了有关 socket API的变化,这些变 化在Solaris 2.x和ip(7)的文档中也提供了。
这里暗示一个主机通过组地址和接口来识别一个多播组。主机必须保留一个表,此表中 包含所有至少含有一个进程的多播组以及多播组中的进程数量。
13.3.2 IGMP 报告和查询
多播路由器使用 IGMP报文来记录与该路由器相连网络中组成员的变化情况。使用规则如
下:
1) 当第一个进程加入一个组时,主机就发送一个 IGMP报告。如果一个主机的多个进程加 入同一组,只发送一个 IGMP报告。这个报告被发送到进程加入组所在的同一接口上。
2) 进程离开一个组时,主机不发送 IGMP报告,即便是组中的最后一个进程离开。主机知 道在确定的组中已不再有组成员后,在随后收到的 IGMP查询中就不再发送报告报文。
3) 多播路由器定时发送 IGMP查询来了解是否还有任何主机包含有属于多播组的进程。多 播路由器必须向每个接口发送一个 IGMP查询。因为路由器希望主机对它加入的每个多播组均 发回一个报告,因此 IGMP查询报文中的组地址被设置为 0。
4) 主机通过发送 IGMP报告来响应一个 IGMP查询,对每个至少还包含一个进程的组均要 发回IGMP报告。
使用这些查询和报告报文,多播路由器对每个接口保持一个表,表中记录接口上至少还 包含一个主机的多播组。当路由器收到要转发的多播数据报时,它只将该数据报转发到(使用相应的多播链路层地址)还拥有属于那个组主机的接口上。
图13-3显示了两个 IGMP报文,一个是主机发送的报告,另一个是路由器发送的查询。该 路由器正在要求那个接口上的每个主机说明它加入的每个多播组。
IGMP报告,TTL=1, IGMP组地址=组地址 目的IP地址=组地址 源IP地址=主机的IP地址
IGMP查询,TTL=1, IGMP组地址=0 目的IP地址=224.0.0.1 源IP地址=路由器IP地址