定时任务在开发中是非常常见的一个需求,定时检测过期优惠券、定时重启、刷新缓存、备份数据等等都可以用到定时任务。在 Linux 上一般都是通过 crontab 来实现一个定时任务,这个是基于操作系统的;当然在应用层面也是可以实现的,如使用 Swoole 的定时器,Laravel 框架的任务调度(本质上也是 crontab ), Quartz 分布式任务调度框架等等。但是基于应用层面的定时任务局限性比较大,一般都是只能使用特定的语言来开发;比如 Swoole 一般都只能用 PHP 来开发;而通过 crontab 命令,我们可以在固定的时间间隔执行指定的系统指令或 shell 脚本,基本上就不限制于开发语言了。

定义方式

在 Linux 下定义一个定时任务有两种方式,一个是直接修改 /etc/crontab 文件,还有一个是通过 crontab -e 命令来编辑任务文件。这两种方式的区别如下:

  • 定义方式不同

直接修改 /etc/crontab 的话在定义的时候需要在 command 之前指定一个命令的执行用户

  • 范围不同

修改 /etc/crontab 只有 root 用户能用,可以更加方便的给其他用户设置计划任务;
crontab -e 这种所有用户都可以使用,普通用户也只能为自己设置计划任务,然后会自动写入 /var/spool/cron/usename

  • 系统级任务与用户级任务

系统级任务调度主要完成系统的一些维护操作,用户级任务调度主要完成用户自定义的一些任务,可以将用户级任务调度放到系统级任务调度来完成(不建议这么做),但是反过来却不行;root 用户的任务调度操作可以通过 crontab –uroot –e 来设置,也可以将调度任务直接写入 /etc/crontab 文件;需要注意的是,如果要定义一个定时重启系统的任务,就必须将任务放到 /etc/crontab 文件,即使在 root 用户下创建一个定时重启系统的任务也是无效的。

如何使用

命令格式

crontab 的命令格式很简单,这个是定义任务的,而不是定义任务文件(任务文件就是定义实际的什么时间节点以及执行什么任务)

crontab [-u user] file crontab [-u user] [ -e | -l | -r ]

简单说一下参数的含义:

-u user:用来设定某个用户的 crontab 服务
file:  file 是命令文件的名字,指定一个文件并且该文件中写好了各个定时任务, 然后 crontab 会读取该文件内容并且载入 crontab
-e:    编辑某个用户的 crontab 文件内容, 默认编辑当前用户的 crontab 文件
-l:    显示某个用户的 crontab 文件内容,默认显示当前用户的 crontab 文件内容
-r:    从 /var/spool/cron 目录中删除某个用户的 crontab 文件,默认删除当前用户的 crontab 文件
-i:    在删除用户的 crontab 文件时给确认提示

crontab 的文件格式

以上是使用 crontab 命令时的参数以及含义,这个文件格式才是真正定义时间和任务的。格式如下:

*  *  *  *  *  *

具体含义是:

第 1 列分钟 0~59
第 2 列小时 0~23(0表示子夜)
第 3 列日 1~31
第 4 列月 1~12
第 5 列星期 0~7(0和7表示星期天)
第 6 列要运行的命令

可以看一张图片来加深记忆:

在使用的时候可以直接通过 crontab -e 来打开并且编辑当前的定时任务配置文件, 然后可以通过 crontab -l 来列出 crontab 文件内容.

常用实例

  1. 每1分钟执行一次 command
* * * * * command
  1. 每小时的第 3 和第 15 分钟执行
3,15 * * * * command

这个很有用, 特别是在定时抓取一些开彩数据就可以用到, 你懂的。

  1. 在上午 8 点到 11 点的第 3 和第 15 分钟执行
3,15 8-11 * * * command
  1. 每周一上午 8 点到 11 点的第 3 和第 15 分钟执行
3,15 8-11 * * 1 command
  1. 每晚的 21:30 重启 smb
30 21 * * * /etc/init.d/smb restart
  1. 每一小时重启 smb
* */1 * * * /etc/init.d/smb restart
  1. 晚上 11 点到早上 7 点之间,每隔一小时重启 smb
0 23-7 * * * /etc/init.d/smb restart

常见问题

环境变量问题

有时候创建了一个任务,但是这个任务却无法自动执行,而手动执行这个任务却没有问题,这种情况一般是由于在 crontab 文件中没有配置环境变量引起的。
在 crontab 文件中定义多个调度任务时,需要特别注环境变量的设置,因为我们手动执行某个任务时,是在当前 shell 环境下进行的,程序当然能找到环境变量,而系统自动执行任务调度时,是不会加载任何环境变量的,因此,就需要在 crontab 文件中指定任务运行所需的所有环境变量。建议在定义任务的时候路径都使用绝对 路徑。

执行时间

基本上 crontab 的最低检测时间单位是分钟,所以会每分钟读取一次 /etc/crontab/var/spool/cron 中的数据内容;因此只要编辑完文件并且保存之后,crontab 时设定就会自动执行;当然如果重启 crontab 则可以立即执行了。当 crontab 失效时,可以尝试重启:

/etc/init.d/crond restart

或者查看日志看某个任务有没有执行报错:

tail -f /var/log/cron

附上 Ubuntu 上的重启命令:

$sudo /etc/init.d/cron start
$sudo /etc/init.d/cron stop
$sudo /etc/init.d/cron restart

系统日志

每条任务调度执行完毕,系统都会将任务输出信息通过电子邮件的形式发送给当前系统用户,这样日积月累日志信息会非常大,可能会影响系统的正常运行;因此,将每条任务进行重定向处理非常重要,可以在定义任务的时候忽略日志输出:

0 */3 * * * /usr/local/apache2/apachectl restart >/dev/null 2>&1

欢迎关我的个人公众号:左手代码


wh469012917
331 声望25 粉丝

« 上一篇
Let's Encrypt