9.8 用cron进行调度

通常我们需要安排脚本在某个时间或每隔一段时间来运行。GNU/Linux系统包含了各种用于调度任务的工具。cron就是其中之一,它通过守护进程cron使得任务能够以固定的时间间隔在系统后台自动运行。cron利用的是一个被称为“cron表”(cron table)的文件,这个文件中存储了需要执行的脚本或命令的调度列表以及执行时间。这个工具非常有用,一个常见的用例是设置在免费时段(free hour)(这是一些ISP提供免费服务,通常将时间设定在大多数人都已入睡的午夜)从Internet上进行下载。用户完全不需要在夜里熬红双眼等待下载。只需要编写一个cron条目,然后调度下载即可。你也可以安排当免费时段结束后自动断开Internet连接并关机。

9.8.1 新手上路

所有的GNU/Linux发行版都默认包含了cron调度工具。只要我们在cron表中写入条目,对应的命令就会在指定的时间执行。命令crontab用来添加调度条目。一次cron调度其实就是一段简单的文本。每一位用户都有自己的cron调度,通常这也被称为一个cron作业(cron job)。

9.8.2 实战演练

要想进行任务调度,我们得知道cron表的格式。一个cron作业指定了需要执行的脚本或命令的路径以及执行时间。cron表的每一个条目都由6部分组成,并按照下列顺序排列:

  • 分钟(0~59)

  • 小时(0~23)

  • 天(1~31)

  • 月份(1~12)

  • 工作日(0~6)

  • 命令(在指定时间执行的脚本或命令)

前5部分指定了某个命令实例所要执行的时间。当然还有其他选项也可用以指定调度时间。

星号(*)指定命令应该在每一个时间阶段执行。也就是说,如果*是写在cron作业中的小时字段中,那么命令就会每小时执行一次。与此类似,如果你希望在某个特定时段执行命令,那么就在对应的时间字段中指定时段,并用逗号分隔(例如要在第5分钟和第10分钟运行命令,那就在分钟字段中输入"5, 10")。还有另一个不错的选项可以让我们以特定的时间间隔运行命令。在分钟字段使用*/5,可以每5分钟运行一次命令。这个技巧可以用在任何时间字段。一个cron表条目是由一行或多行cron作业组成的。cron表条目中的每一行都是一项作业。例如:

  • 编写一个crontab条目的样例:
  1. 02 * * * * /home/slynux/test.sh

这个cron作业会在每天各小时的第2分钟执行脚本test.sh。

  • 要在每天的第5、6、7小时执行脚本:
  1. 00 5,6,7 * * /home/slynux/test.sh
  • 在周日的每个小时执行脚本script.sh:
  1. 00 */12 * * 0 /home/slynux/script.sh
  • 在每天凌晨2点钟关闭计算机:
  1. 00 02 * * * /sbin/shutdown -h

现在,让我们看看如何调度一项cron作业。执行crontab命令进行调度的方法有很多种。

如果你手动运行crontab,用选项 -e输入cron作业:

  1. $ crontab -e
  2. 02 02 * * * /home/slynux/script.sh

当输入crontab -e后,会打开默认的文本编辑器(通常是vi)供用户输入cron作业并保存。这项cron作业将会在指定的时间被调度执行。

如果我们在脚本中调用crontab进行任务调度,那么有另外两种方法可供使用:

  • 创建一个文本文件(例如task.cron),并写入cron作业。

然后将文件名作为命令参数,运行crontab

  1. $ crontab task.cron
  • 通过下面的方法,我们可以在行内(inline)指定cron作业,而无需创建单独的文件。例如:
  1. crontab<<EOF
  2. 02 * * * * /home/slynux/script.sh
  3. EOF

cron作业需要写在crontab<EOF之间。

执行cron作业所使用的权限同执行crontab命令所使用的权限相同。如果你需要执行要求更高权限的命令,例如关闭计算机,那么就要以超级用户身份执行crontab

cron作业中指定的命令需要使用完整路径。这是因为执行cron作业时的环境与终端所使用的环境不同,因此环境变量PATH可能都没有设置。如果命令运行时需要设置某些环境变量,你应该明确设定出来。

9.8.3 补充内容

crontab命令还有其他选项。让我们看看其中一部分。

  • 指定环境变量

很多命令需要正确的设置环境变量才能够运行。我们可以在用户的cron表中插入一行变量赋值语句来设置环境变量。

例如,如果你使用的是代理服务器连接Internet,要调度某个需要使用Internet的命令,你就得设置HTTP代理环境变量http_proxy,可以用下面的方法来完成:

  1. crontab<<EOF
  2. http_proxy=http://192.168.03:3128
  3. 00 * * * * /home/slynux/download.sh
  4. EOF
  • 查看cron

我们可以用选项-l列出现有的cron表中的内容:

  1. $ crontab -l
  2. 02 05 * * * /home/user/disklog.sh

crontab -l会列出当前用户cron表中的已有条目。

我们也可以通过选项 -u指定用户名来查看其他用户的cron表:

  1. $ crontab -l -u slynux
  2. 09 10 * * * /home/slynux/test.sh

当使用选项-u时,你应该使用超级用户以获取更高的权限。

  • 移除cron

可以用选项-r移除当前用户的cron表:

  1. $ crontab -r

要移除其他用户的cron表,可以使用:

  1. # crontab -u slynux -r

这需要以超级用户身份获得更高的权限。