Chinaunix首页 | 论坛 | 博客
  • 博客访问: 379370
  • 博文数量: 190
  • 博客积分: 50
  • 博客等级: 民兵
  • 技术积分: 125
  • 用 户 组: 普通用户
  • 注册时间: 2013-01-12 14:05
文章分类

全部博文(190)

文章存档

2013年(190)

我的朋友

分类: LINUX

2013-03-06 09:48:49

通过实现管理任务的自动化,可以节约大量的时间,而 UNIX® 中就包含了可帮助实现此过程自动化的系统。在本文中,您将了解使用这些系统的最佳方法,包括如何监视和跟踪其执行和输出,以及如何计划复杂事件。

关于本系列

通常,UNIX 管理员都拥有一套他/她经常使用协助管理进程的实用程序、技巧和系统。提供了各种用于简化不同过程的关键实用工具、命令行链和脚本。这些工具中有一部分来自于操作系统,而大部分的技巧则来源于长期的经验和简化系统管理员工作的要求。本系列文章主要专注于最大限度地利用各种 UNIX 环境中可用的工具,包括简化异类环境中的管理任务的方法。

及时管理中的计划

典型的系统管理员会花很多时间进行重复的任务。至少在没有可在合适的时间点运行各种任务的任务计划系统的情况下,他们会这样做。

典型的例子包括运行备份之类的日常任务,也包括要每周或每个月执行的各种任务,如清理日值、生成报告以及在各种情况下要执行的大量其他命令。

另外还有其他希望以特定时间间隔运行的任务,例如监视当前运行的进程或当前磁盘使用量列表的命令,所有此类任务都可以用于帮助在出现故障或其他问题时诊断和确定问题。或者,可能存在希望在自己不在场的特定时间执行的命令。例如,您可能会希望在夜间关闭为第二天工作做准备的计算机,但您可能不希望仅为了关闭计算机而一直等到午夜。

有可用于所有这些情况的解决方案,但在了解如何执行这些操作前,应该注意到计划方法的一些缺点和不足。

由于所有任务都已自动化,计划执行的一个主要问题是,如果发生了任何错误或意外的情况,并没有机会对出现的问题加以解决。另外,您还完全依赖于系统及其在特定时间执行特定任务的功能。在命令何时执行方面有一些限制,而处理“如果发生了 X,则执行 Y,否则执行 Z”之类的不可预测的情况要求进行脚本编写,并需要进行很多次试验,可能遇到很多错误。

不过,计划可以节约大量的时间,因此这些选项值得考虑。

计划一次性执行的任务

cron 系统可处理所有基于时间的命令执行计划,并提供了可用于在特定时间运行命令的两个不同解决方案。at 命令可计划在特定的时间执行某项任务,且仅执行一次。crontab 系统允许指定命令的执行计划,可以在指定的时间运行,可以在特定某天运行,还可以将二者结合使用。

可采用两种方法使用 at 命令。第一个是直接键入 at 和希望命令运行的时间(可以选择指定日期)。例如:
  1. $ at 17:20 
  2. echo It's 17:20!
  3. job 1 at Tue Apr 11 17:20:00 2006
复制代码
输入了 at 命令后,它将等待您输入要在指定时间运行的命令。可以输入任意多的命令,这些命令将作为 Shellscript 执行。要终止输入,请使用 end-of-file 命令(通常为 Control-D)。

您所键入的命令将在调用 at 命令的环境副本中执行。这意味着,将记录您的活动 PATH、库和其他环境设置,并用于执行您生成的脚本。通常会在命令完成时将结果通过电子邮件发送给您。

指定时间时,可以使用标准时间格式(如前面的示例中所示),也可以使用其他各种缩写技术。如果指定了时间,则将使用该时间的下一个匹配项。例如,如果当前时间是 17:00,而您指定的时间是 17:20,命令将在 20 分钟后执行。如果指定 09:00,则命令将在第二天的上午 9 点执行。

通常可以使用以下特殊的替换项:

   * midnight——12:00 a.m./00:00
   * noon——12:00 p.m.
   * now——立即执行

还可以使用 today 和 tomorrow。一些环境(BSD 和 Linux®)还可能支持通过加上表示分、时、天、周、月和年的数值来增加指定值的时间的选项。例如,可以使用以下命令来指定某个作业在一周后的当前时间运行:
  1. $ at now + 1 week
复制代码
如果您希望重新计划作业在上次执行之后的一段时间执行,则可以使用这种指定方式。例如,您可能在运行一个运行时间长达数小时的报告,但又希望在一周后再次运行次报告。 

检查计划作业

要获取当前的计划作业列表,请使用 -l 命令行选项:
  1. $ at -l
  2. 1       Tue Apr 11 17:20:00 2006
  3. 2       Wed Apr 12 09:00:00 2006
复制代码
输出中的数字是作业 ID。不过,不可能从标准命令的这个列表中确定每个作业将进行的操作。 

删除计划作业

通过使用 -r 选项,并指定作业首次提交时生成的(或对计划程序中的条目进行列表操作时显示的作业列表列出的)作业号,可以删除计划作业。例如,要删除上面示例中将在 4 月 12 日星期三 09:00 执行的作业,可以使用以下命令:
  1. $ at -r 2
复制代码
请注意,大部分系统将不会提供作业已从队列中删除的可视指示,因此可能需要再次对作业进行列表操作,以确定已取消了相应的作业:
  1. $ at -l
  2. 1       Tue Apr 11 17:20:00 2006
复制代码
计划定期执行的任务

为了定期执行,要设置一个 cron 表(称为 crontab),以定义每个命令执行的间隔和顺序。该文件的格式是这样的,每个命令占单独的一行,每行包括六个字段,如下所示:

minute hour day month dayofweek command



应根据以下规则使用数字进行时间指定:

    * Minute:0-59
    * Hour:0-23
    * Day:1-31
    * Month:1-12
    * Day:0-6(其中 0 是星期日)

对于任何字段,都可以指定单个数字、用逗号分隔的数字列表或星号(指示应匹配任何值)。

通过指定时间,只要匹配当前时间,就会执行命令。例如,通过指定以下时间:0 * * * * do-something,命令将在当前时间的分钟值为 0 时(例如整点时)执行。

而指定以下时间:0 23 * * * do-something,命令将在每晚 11 点时运行。

如果指定多个值,则会对每个值进行匹配。例如,要每 15 分钟执行一次命令,请使用以下语句:
  1. 0,15,30,45 * * * * do-something
复制代码
或者,可以通过使用以下命令指定命令从星期一到星期五每六个小时运行一次:
  1. 0 0,6,12,18 * * 1,2,3,4,5 do-something
复制代码
可以在 crontab 中包含任意多的行,如果希望,可以多次引用相同的命令,而这在其他情况下则相当难于实现。例如,一个命令要在星期一到星期四的下午 6 点运行,但在星期五时要在午餐时间运行,则可以使用以下两行语句:
  1. 0 18 * * 1,2,3,4 do-something
  2. 0 12 * * 5 do-something
复制代码
对于前两个选项(分和时)应该小心处理;如果未指定这两个选项(使用星号),将导致在匹配其他指定值的情况下,每分钟运行一次。例如,一个常见的错误是,希望在月初运行命令,但却使用了以下语句:
  1. * * 1 * * do-something
复制代码
这里的问题是,上述指定语句实际上会在每个月的第一天每分钟运行该命令一次。如果希望命令只运行一次,必须指定应执行命令的分和时的值:
  1. 0 12 1 * * do-something
复制代码
省略分钟值,将至少让命令在匹配指定的时(和日期)的情况下每分钟运行命令一次。

虽然有这么大的灵活性,但仍然会出现很难(甚至不可能)使用 crontab 系统执行命令的情况。 

处理手动计划

cron 的问题在于,尽管 crontab 中可用的所有不同选项提供了各种不同的可能性,但仍然有一些恼人的局限。

每月的最后一天

例如,要在 cron 中每月最后一天运行命令很困难,因为没有办法直接指定此信息。相反,您必须单独指定月份和其对应的最后一天。例如,在不是闰年的年份,可以结合使用以下三行语句:
  1. 59 23 31 1,3,5,7,8,10,12 * do-something
  2. 59 23 30 4,6,9,11        * do-something
  3. 59 23 28 2               * do-something
复制代码
在上面的示例中,通过手动的方式选择了每个月的最后一天,但管理这三行可能有些麻烦,必须在闰年手动修改 crontab 定义,以确保该信息能计算出正确的日期。

相应的解决办法是使用 echo 命令(而不是 cron)执行日期检查。要实现这一点,需要使用 cal(用于输出当前月份的日历)和 awk(用于确定该月的最后一天)。如果运行以下命令,应该可获得月份的最后一天:
  1. $ echo `cal`|awk '{print $NF}'
复制代码
以上命令首先通过 echo 命令(会将通常的多行输出作为一行输出)输出日历,然后对输出的数字进行计数;最后的数字就是当前月份的最后一天。

要在 crontab 中使用此命令,应采用以下方式:
  1. 59 23 * * * [`echo \`cal\`|awk '{print $NF}'` -eq `date +\%d`] 
  2. && do-something
复制代码
方括号将在用于运行命令的外壳程序中启动一个测试。另外要注意,cron 将筛选出 % 符号,因此在 crontab 中使用时必须进行转义。该测试的第一部分就是前面演示的内容,其第二部分使用 date 命令来输出当前日期。重复的 && 可确保 && 右侧的命令仅在左侧的测试结果为真时执行。

给定周中的特定天

另一个常见的需求是,仅在每月中的特定星期数运行。例如,可能希望在每个月的第一个星期一或星期五运行一个报告。为了完成此任务,可以使用与上面类似的过程。对于给定周中的任何天,它一定属于以下日期范围之一:

    * 第 1 周:第 1 天到第 7 天
    * 第 2 周:第 8 天到第 14 天
    * 第 3 周:第 15 天到第 21 天
    * 第 4 周:第 22 天到 28 天

要确定当前日期是否在给定范围内,例如是否在第四周范围内,可以使用与以下所示类似的测试:
  1. [ `date +\%e` -gt 21 -a `date +\%e` -lt 29 ]
复制代码
%e 用于返回当天的号数,如果数字小于 10 则用一个空格(而不是零)作为其前缀,以确保对数字(而非字符串)进行比较。

现在可以将此与 crontab 定义一起使用,以尝试每周星期五运行命令:
  1. 59 23 * * 5 [ `date +\%e` -gt 21 -a `date +\%e` -lt 29 ]
  2. && do-something
复制代码
命令将在每周星期五运行,但由于测试将仅在每个月的第四周返回 True,命令将实际在第三个星期五执行。 

Cron 作业执行环境

尽管可以更改执行 cron 作业时使用的环境,但经常最好创建一个包装脚本,以在运行实际需要的命令前定义任何环境变量(如 PATH)。

这样做的部分原因是出于安全考虑;向 cron 作业开放的区域越多,越可能得到包含可疑内容的东西。另一个原因是,这样可确保即使更改了环境中的一个依赖关系,您的 cron 作业仍然将执行。

通过使用独立的包装脚本,还可以利用不同外壳程序的扩展和功能,而不仅限于通常用于运行大部分 cron 作业的标准 Bourne 外壳程序。

最后,通过使用独立的包装脚本,还允许您为不同命令定义不同的环境。如果您希望在可能使用相同应用程序或工具的不同版本的不同用户环境中运行命令,这将非常有用。 

记录输出的技巧

缺省情况下,crontab 运行的生成输出(到标准输出和标准错误的输出)的命令都会将输出以电子邮件的形式发送给该作业的用户。不过,这并非总是方便的解决方案,对于某些结果,您可能只需要部分输出,或者可能希望忽略标准输出,而仅报告错误。甚至可能希望将输出发送到不同的用户或电子邮件别名。

可以在 crontab 指定语句中使用重定向来将输出信息发送到特定文件或忽略来自不同源的输出。要直接将输出记录到文件中,可以使用以下语句:
  1. 1 1 * * * do-something >/var/logs/do-something.log
复制代码
上述语句会覆盖信息,因此,如果希望保持较长时间的记录,请使用追加:
  1. 1 1 * * * do-something >>/var/logs/do-something.log
复制代码
要忽略输出,请重定向到特殊的 /dev/null 设备。对于标准输出,请尝试使用以下语句:
  1. 1 1 * * * do-something >/dev/null
复制代码
对于标准输出和错误,请尝试使用以下语句:
  1. 1 1 * * * do-something >/dev/null 2>&1
复制代码
如果希望收集按照日期组织的日志,则请将 date 命令和指定日志文件的语句结合使用,例如:
  1. 1 1 * * * do-something >/var/logs/something.`date +\%Y\%m\%d`.log
复制代码
要从 cronjob 中的一系列命令拾取和选择输出,或创建基于内容的自定义电子邮件,请使用包装脚本,以将您希望保存的信息写入到临时文件中,并同时忽略其他输出。可以随后将该文件的内容以电子邮件的方式发送给任何希望的用户。

要创建临时文件,请使用时间和进程 ID 生成唯一的文件名,如下所示:
  1. LOGFILE=/tmp/`datetime +%Y%m%d`.$$.tempfile
  2. do-something >$LOGFILE 2>&1
  3. mailx -s "Results of do-something report" reportees <$LOGFILE
  4. rm -f $LOGFILE
复制代码
将文件发送到相关人员后,请记住删除该文件。在上面的示例中,使用了 mailx(而不是 mail)来允许设置主题。 

结束语

通过将 crontab 和 at 命令结合使用,可以指定任何所需的命令的执行时间或间隔。使用 at 时,可以在给定时间仅运行一次命令或脚本。通过使用 crontab,可以指定执行的时间间隔,这个间隔可以随意指定,可以间隔很长,也可以间隔很短。但应仔细处理,以确保命令在所需的准确时间运行。忽略分和时可能带来问题,或者可能导致您的命令在预期外的时间或时间间隔运行。

在 crontab 不够具体或灵活的时候,可以使用其他一些替代方法,以处理更为复杂的情况,例如在每月的最后一天或特定周的特定天运行命令。

进行计划可节省时间,在细心组织下,还能帮助减少您的工作负担,减少重复工作。
阅读(908) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~