定时任务在开发中是非常常见的一个需求,定时检测过期优惠券、定时重启、刷新缓存、备份数据等等都可以用到定时任务。在 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分钟执行一次 command
* * * * * command
- 每小时的第 3 和第 15 分钟执行
3,15 * * * * command
这个很有用, 特别是在定时抓取一些开彩数据就可以用到, 你懂的。
- 在上午 8 点到 11 点的第 3 和第 15 分钟执行
3,15 8-11 * * * command
- 每周一上午 8 点到 11 点的第 3 和第 15 分钟执行
3,15 8-11 * * 1 command
- 每晚的 21:30 重启 smb
30 21 * * * /etc/init.d/smb restart
- 每一小时重启 smb
* */1 * * * /etc/init.d/smb restart
- 晚上 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
欢迎关我的个人公众号:左手代码
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。