ayhome/croantab

Ayhome/croantab 是一个用于 PHP 的 Linux-crontab 命令风格计时器库。

维护者

详细信息

gitee.com/anyhome/DICrontab.git

安装: 2

依赖者: 0

建议者: 0

安全: 0

类型:

v1.0 2016-03-10 05:26 UTC

This package is auto-updated.

Last update: 2024-09-17 09:44:37 UTC


README

这是一个使用类似 Linux crontab 的格式字符串实现定时服务的 PHP 类,依赖于 swoole-extension。

感谢项目 swoole-crontab,我学会了如何分析 crontab 字符串。

DICrontab 与 swoole-crontab 不同,后者是一个完整的应用程序,而 DICrontab 只是一个工具,一个简单的库,一个类,您可以将它包含到您的项目中并使用它。

快速入门

<?php
include './CrontabTicker.php';

$crontab = new \DIServer\Ticker\CrontabTicker();
$crontab->When('0 */20 * * *')
	->Then(function ($userParams)
	{
		echo 'crontab called';
		return false;//return false if you want to cancle this cron.
        }, $userParams
        );
//The callback function will be called every 20 minitues.

如果您只想测试计时器下次何时触发,请使用 Next() 函数代替,Next() 将返回时间表的迭代器。您还可以使用 From(startTime) 假设 cron 从所需时间开始,而不是 time()。

$iterator = $crontab->When('* */20 * * *')
		//->From( mktime(14, 00, 00, 3, 3, 2016) )//Optional
		->Next();

$count = 0;//only print next 10 cron.
foreach($nextTickTime in $iterator)
{
	if($count++ < 10)
		echo $nextTickTime;
	else
		break;
}
//Simple of crontab-string
//$crontabString :
//	 *                       0     1    2    3    4    5
//	 *                       *     *    *    *    *    *
//	 *                       -     -    -    -    -    -
//	 *                       |     |    |    |    |    |
//	 *                       |     |    |    |    |    +----- day of week (0 - 6) (Sunday=0)
//	 *                       |     |    |    |    +----- month (1 - 12)
//	 *                       |     |    |    +------- day of month (1 - 31)
//	 *                       |     |    +--------- hour (0 - 23)
//	 *                       |     +----------- min (0 - 59)
//	 *                       +------------- sec (0-59) (Optional)
//You can use 5 params like what crontab use in Linux, and use the 6th param as to descript the SECONDS.

依赖关系

  • 我的开发环境是 CentOS 7。
  • PHP 7.0.3
  • Swoole-extension 1.8.3
  • 我认为 php5.5+ 和 swoole 1.7.7+ 是可以的,但我没有测试过。
  • 我使用了 swoole_timer_after,所以至少需要 swoole-1.7.7。
  • 它还使用了 PHP 中的 'yield' 关键字,因此需要 5.5+。

注意

由于此类基于 swoole_timer_after,请在使用 swoole_server 或 asyns-swoole-client 时注意以下内容

  1. 如果进程被重新加载,cron tick 将被删除,因此如果您想添加一个常驻的 crontab,请记录您的 cron-string 并在进程启动时初始化计时器,一些 swoole 回调(如 'OnWorkerStart')将描述时间表,不用担心计时器会丢失,只需设置一个新的计时器即可。

  2. 如果您想执行像向每个用户发送一条消息这样的任务,请注意每个进程都可以有自己的计时器,如果您在 OnWorkerStart 中添加了计时器,假设您有 2 个 Worker 进程和 4 个 TaskWorker 进程,并且在每个 Worker 启动时设置了计时器,您将同时拥有 6 个计时器和回调,每个客户端将接收 6 条消息。因此,请使用类似 "if($server->worker_id==0)" 的方式只添加一个计时器。

描述

在我开发自己的 swoole-framework DIServer-framwork 的过程中,我发现实现一些定时任务(如每周一至周五向每个客户端发送消息)并不容易。swoole_tick 提供了高精度计时服务,但它只能每隔相同的微秒或从现在开始的一定微秒后计时。

我需要的是类似 Linux 中的 crontab,可以使用格式字符串轻松实现,例如 "0 0 * * mon-fri",并且当时间到达时将调用回调函数。

最初我只是想将其用作 DIServer-framwork 的插件,但完成后我发现它是一个独立的工作,因此创建了此项目。

差异

由于 swoole-extension 提供的高精度,与 Linux-crontab 不同,我们可以设置高级 cron,如 "*/20 0 0 * * fri",使用 6 个参数,格式为 "second minute hour day month week";使用 5 个参数的格式为 "minute hour day month week",它将在该分钟的 1 秒时调用,就像 Linux-crontab 一样。

示例

以下是我在测试 Ticker 时使用的一些示例,如果您发现任何错误,请 注释 我。

private $cronString = [
		'* */1 * 3 3 *'          => 'every seconds in Mar 3th.',
		'30 30 21 * * *'         => '21:30:30 on every day.',
		'15,30,45,0 * 23 * * 6'  => 'every 0,15,30,45 seconds in 23 every Saturday.',
		'0 0 */1 * * *'          => 'every hour at 0 minute and 0 seconds.',
		'0 0 4 1 jan *'          => 'every 4:00:00 at January 1st.',
		'* * 7 * * *'            => 'every seconds in 7 o'clock every day.',
		'0-59/2 20 0-23/2 * * *' => 'every 2 seconds in every 20 minutes at every 2 hours in a day.',
		'0 6-12/3 * 2 *'         => 'In February, every 3 hours in 6 o'clock to 12 o'clock.',
		'0 17 * * 1-5'           => 'every 17:00:01 on Monday to Friday.',
		'0 11 4 * mon-wed'       => 'Every 11:00:01 on 4th of a month or in Monday to Wednesday',
		'10 1 * * 6,0'           => 'every 1:10:01 on Saturday and Sunday',
		'45 4 1,10,22 * *'       => '4:45:01 on every 1st,10th,22th in a month.',
		'0,30 18-23 * * *'       => 'every 0,30 minutes in 18-23. Tips:23:30 will called.',
		'*/1 * * * * *'          => 'every seconds',
		'* * * * * *'            => 'every seconds',
		'0 23-7/1 * * *'         => 'equals to "0 23,0-7 * * *"',
	];

缩写

在使用月份或星期时,您可以使用 'fri' 来代替 '5',表示星期五,缩写支持如下

//Case is ignored
const SHORT_MAP = [
		'sun'       => 0,
		'sunday'    => 0,
		'mon'       => 1,
		'monday'    => 1,
		'tues'      => 2,
		'tue'       => 2,
		'tuesday'   => 2,
		'wed'       => 3,
		'wednesday' => 3,
		'thur'      => 4,
		'thu'       => 4,
		'thursday'  => 4,
		'fri'       => 5,
		'friday'    => 5,
		'sat'       => 6,
		'saturday'  => 6,
		'jan'       => 1,
		'january'   => 1,
		'feb'       => 2,
		'february'  => 2,
		'mar'       => 3,
		'march'     => 4,
		'apr'       => 4,
		'april'     => 4,
		'may'       => 5,
		'jun'       => 6,
		'june'      => 6,
		'jul'       => 7,
		'july'      => 7,
		'aug'       => 8,
		'august'    => 8,
		'sep'       => 9,
		'sept'      => 9,
		'september' => 9,
		'oct'       => 10,
		'october'   => 10,
		'nov'       => 11,
		'november'  => 11,
		'dec'       => 12,
		'december'  => 12
	];