一、环境基础
EasyTask的linux环境要求如下(推荐使用宝塔集成环境):
PHP版本大于或者等于 5.4
PHP开启json扩展(默认已开启)
PHP开启pcntl扩展(默认已开启)
PHP开启posix扩展(默认已开启)
PHP开启event扩展(需要手动开启,非强制要求安装,安装性能更强)
PHP正确配置环境变量
二、基础入门
1.安装Composer包:
composer require easy-task/easy-task
执行上面的命令如果提示git is not recognized,说明你没有安装git,附上阿里巴巴的git镜像下载地址:
[http://npm.taobao.org/mirrors/git-for-windows/](阿里巴巴git)
2.安装完成引入:
require './vendor/autoload.php';
//初始化
$task = new EasyTask\Task();
// 设置非常驻内存
$task->setDaemon(false);
// 设置项目名称
$task->setPrefix('EasyTask');
// 设置记录运行时目录(日志或缓存目录)
$task->setRunTimePath('./Application/Runtime/');
// 1.添加闭包函数类型定时任务(开启2个进程,每隔10秒执行1次)
$task->addFunc(function () {
$url = 'https://www.gaojiufeng.cn/?id=243';
@file_get_contents($url);
}, 'request', 10, 2);
// 2.添加类的方法类型定时任务(同时支持静态方法)(开启1个进程,每隔20秒执行1次)
$task->addClass(Sms::class, 'send', 'sendsms', 20, 1);
// 3.添加指令类型的定时任务(开启1个进程,每隔10秒执行1次)
$command = 'php /www/web/orderAutoCancel.php';
$task->addCommand($command,'orderCancel',10,1);
// 启动任务
$task->start();
3.代码解析
(3.1).setDaemon(false)
设置非后台运行,在windows下会启动php进程执行代码,你会看到几个黑色窗口在执行代码,在linux下会在当前终端执行代码。
(3.2).setDaemon(true)
设置后台运行,在windows下让进程在后台运行你看不到执行界面,在linux会常驻在内存中就算你关闭命令行窗口依然在执行。
(3.3).setPrefix('项目名称')
为当前的项目设置一个别名,推荐为英文,主要目的是为了方便区分项目,可以自定义。
(3.4).setRunTimePath('运行缓存或日志路径')
设置一个EasyTask运行日志和缓存文件保存的目录。
(3.5).addFunc(闭包函数,任务名称,执行间隔时间,启动进程数)
添加一个任务,每间隔多少秒执行下您设置的闭包函数中的代码。例如上面中在闭包函数设置请求一个url,每隔10秒执行一次闭包函数,并且开启了2个进程,那么10秒后闭包函数被执行2次
(3.6).addClass('类名称','类的方法','任务名称',执行间隔时间,启动进程数)
添加一个任务,每间隔多少秒执行下您设置的类的某个方法。例如上面的例子中每隔20秒就会执行您设置的Sms类的send方法
(3.7).addCommand('cmd/shell命令',任务名称,执行间隔时间,启动进程数)
添加一个任务,每间隔多少秒执行下您设置cmd命令或者shell命令,例如上面的例子中每隔10秒执行1次“php /www/web/orderAutoCancel.php”命令
(3.8).start()
启动添加的所有任务,启动后window下任务管理器即可看到对应的进程信息,切换详情信息即可看到启动的进程id,linux下可以使用ps aux|项目名称查看已经启动的进程id;如果是windows下同步模式启动,可以直接关闭所有cmd窗口即可关闭所有任务,如果是linux同步模式启动,直接按ctrl+c即可关闭所有任务
三、命令整合
// 获取命令
$force = empty($_SERVER['argv']['2']) ? '' : $_SERVER['argv']['2'];
$command = empty($_SERVER['argv']['1']) ? '' : $_SERVER['argv']['1'];
// 配置任务
$task = new Task();
$task->setRunTimePath('./Application/Runtime/');
$task->addFunc(function () {
$url = 'https://www.gaojiufeng.cn/?id=271';
@file_get_contents($url);
}, 'request', 10, 2);;
// 根据命令执行
if ($command == 'start')
{
$task->start();
}
elseif ($command == 'status')
{
$task->status();
}
elseif ($command == 'stop')
{
$force = ($force == 'force'); //是否强制停止
$task->stop($force);
}
else
{
exit('Command is not exist');
}
启动任务: php console.php start
查询任务: php console.php status
普通关闭: php console.php stop
强制关闭: php console.php stop force
四、主函数说明
主函数说明
1.setDaemon($daemon = false)
用来设置任务是否在后台运行,默认是非后台运行。
2.setPrefix($prefix = 'Task')
用来设置项目名称或者任务前缀,默认值是Task,设置项目名称有助于进程日志区分,避免多个项目同时相同的运行时,建议每个项目单独设置一个值。项目名称作为任务前缀也会显示到进程标题中。例如windows非后台运行你可以看到dos窗口的标题,linux下可以通过进程管理看到进程标题携带任务前缀。
3.setPhpPath($path)
用来设置php.exe的位置,默认不用设置,会自动获取,如果获取失败需要自己设置。当然如果你想让执行你的任务使用其他版本的PHP来执行,也可以使用此api来实现。此api仅windows下设置有效。切记!切记!举个栗子:
$task->setPhpPath('C:/phpEnv/php/php-7.0/php.exe');
(4).setAutoRecover($isRec = false)
用来设置任务挂掉是否自动重启,默认是关闭的,例如你在任务中编写了不规范的代码导致内存溢出,执行任务的进程会挂掉,此时EasyTask会重新启动您的进程。
(5).setCloseErrorRegister($isReg = false)
用来设置关闭EasyTask底层的异常注册,默认是不会关闭。如果开启EasyTask将不再监听set_error_handler/set_exception_handler/register_shutdown_function事件。例如您自己编写框架时不想要EasyTask处理异常注册可以设置关闭。
(6).setErrorRegisterNotify($notify)
用来自定义EasyTask出现异常的处理方式,例如您的任务出现异常想要通知自己的邮件或者短信,那么你就可以使用此方法来实现。
用法1:您传递闭包函数,当发生异常我们会向您的闭包函数传递一个异常句柄
$task->setErrorRegisterNotify(function ($ex) {
//获取错误信息|错误行|错误文件
$message = $ex->getMessage();
$file = $ex->getFile();
$line = $ex->getLine();
//发生邮件和短信的代码自己来写在这里
})
用法2:您传递1个url地址,当发生异常我们会向您的url地址发送post数据,您的url可以自定义处理.。
$task->setErrorRegisterNotify('https://www.gaojiufeng.cn/rev.php');
post参数:
errStr:错误信息
errFile:错误文件
errLine:错误行
为什么有两种用法?因为方法1需要您编写代码稳定,否则影响整个进程,当您有足够的信心编写足够健壮的代码的话您可以使用第一种方式。否则请用第二种方式,在您的url地址中对应控制器编写发送短信或者邮件的操作。
(7).setTimeZone($timeIdent)
用来自定义时区,默认EasyTask并不会设置时区。
$task->setTimeZone('Asia/Shanghai');
(8).setRunTimePath($path)
用来设置EasyTask运行时的日志或者缓存保存的目录地址,如果不设置默认保存在PHP临时文件目录,PHP临时文件目录的地址具体的位置可以使用sys_get_temp_dir()函数来获取
$task->setRunTimePath('./runtime/');
(9).addFunc($func, $alas, $time = 1, $used = 1)
用来添加一个闭包类型的任务,你可以把想执行的代码写在闭包函数中。
参数1:闭包函数,你需要重复执行的代码写在里面
参数2:任务别名,您为任务起的别名,尽量不要重复
参数3:任务执行间隔,默认值为秒,如果开启event扩展会支持毫秒
参数4:开启几个进程执行
$task->addFunc(function () {
$url = 'https://www.gaojiufeng.cn/?id=319';
file_get_contents($url);
}, 'request', 10, 1);
上面的代码在10秒后对应的网址会被访问1次
$task->addFunc(function () {
$url = 'https://www.gaojiufeng.cn/?id=319';
file_get_contents($url);
}, 'request', 10, 2);
上面的代码在10秒后对应的网址会被访问2次,因为开启了2个进程
(10).addClass($class, $func, $alas, $time = 1, $used = 1)
用来添加一个类的方法作为任务,你可以把想要执行的类的方法放在这里运行。
参数1:想要执行的类名称,包含完整的命名空间地址
参数2:想要执行的类的某个方法,支持普通pulic方法和静态方法
参数3:任务别名,您为任务起的别名,尽量不要重复
参数4:任务执行间隔,默认值为秒,如果开启event扩展会支持毫秒,也支持crontab表达式
参数5:开启几个进程执行
$task->addClass(Sms::class, 'send', 'send_sms_task', 20, 1)
上面的代码会在20秒后执行Sms类的send方法
(11).addCommand($command, $alas, $time = 1, $used = 1)
用来添加一条cmd命令或者shell命令作为任务,你可以将要执行的命令放在这里运行
参数1:想要执行的cmd命令或者shelll命令
参数2:任务别名,您为任务起的别名,尽量不要重复
参数3:任务执行间隔,默认值为秒,如果开启event扩展会支持毫秒,也支持crontab表达式
参数4:开启几个进程执行
$task->addCommand('php /www/wwwroot/learn/curl.php','cmd',6,3)
上面的代码每隔6秒会执行3次上面命令
(12).start()
启动所有任务,建议配合status,stop整合命令使用。如果是windows下同步模式启动,可以直接关闭所有cmd窗口即可关闭所有任务,如果是linux同步模式启动,直接按ctrl+c即可关闭所有任务
(13).status()
查看任务状态,建议配合start,stop整合命令使用
(14).stop($force = false)
关闭所有任务,建议配合start,status整合命令使用
默认是非强制关闭,第二个参数如果是true则认为是强制关闭。
普通关闭任务:向守护进程发送退出命令,守护进程安全退出,执行的定时器会本次执行完成后安全退出。全部退出后在日志中能看到。
强制关闭任务:向守护进程发送退出命令,守护进程强制杀死运行中的定时器,然后守护进程自己退出进程。执行完成基本立即全部退出。
(15).setCloseStdOutLog($close= false)
默认EasyTask在常驻运行中会将程序运行中的输出(echo/var_dump/printf)保存到Std文件中,方便用户进行查看和调试,但是这是非常占用磁盘空间的,因为有人建议增加此开关,设置为true则不会将你在定时任务中的输出信息保存到Std文件中。我建议用户养成良好的习惯,不要使用此设置,用默认即可,程序在运行中尽量不要输出任何东西,这是非常规范的标准。当然你如果不想保存到EasyTask的运行时文件中可以自己用linux命令重定向输出到其他文件。
五、助手函数说明
为保证安全使用助手函数请在定时器中使用,手册仅列举常用函数
1.Helper::sleep($time,$type = 1)
程序睡眠函数,参数1时间,参数2 类型:1秒 2毫秒
2.Helper::cli_set_process_title($title)
设置进程标题函数
3.Helper::isWin()
检测运行中系统是否是windows
4.Helper::getRunTimePath()
获取运行时目录
5.Helper::getLogPath()
获取日志所在目录
6.Helper::writeLog($message)
写入日志到日志文件
7.Helper::writeTypeLog($message, $type = 'info', $isExit = false)
写入指定类型日志:
参数1:日志文本内容
参数2:日志类型(info|error|exception)
参数3:写完日志是否退出整个进程
8.Helper::convert_char($char, $coding = 'UTF-8')
字符串编码转换函数
9.Helper::showInfo($message, $isExit = false, $type = 'info')
向命令行输出文本,标准框架输出格式,如果开启后台运行模式是看不到的,但是在标准输出文件的日志中可以看到。
参数1:信息文本
参数2:输出完成是否退出进程
参数3:日志类型(info|error|exception)
10.Helper::curl($url, $data = null, $return_array = false, $header = null)
curl请求函数
参数1:请求地址
参数2:POST请求参数,如果非POST请求不需要传递
参数3:是否返回数组结果,如果是json可以设置
参数4:自定义header
六、定时任务执行流程了解
1.通过以下代码分析:
$task->addClass(Sms::class, 'send', 'sendsms', 20, 1);
以上代码的执行流程:
(1).睡眠20秒
(2).执行一次Sms类的send方法,可能需要若干秒
(3).睡眠20秒
(4).执行一次Sms类的send方法,可能需要若干秒
....................
2.通过以下代码分析:
$task->addClass(Sms::class, 'send', 'sendsms', 20, 2);
和上面唯一不同的是多开启1个进程来执行,此时同一时间内有2个进程在执行上面的流程,即并发执行定时任务。
七、为什么不支持异步并发
(1).同步并发简单可控,利于调试
(2).异步并发意义不大,例如你需要添加1秒的定时器,你执行的程序需要耗时10分钟。假如是真正的异步并发,那么随着时间增加整个系统资源将会耗尽,因为你需要执行的任务的资源是递增的。因此目前任何异步并发都会在底层限制,并不会真正的同时并发执行,甚至部分异步定时器通过队列来完成伪异步执行。从某种意义上来讲这是非常愚蠢的。而同步并发完全可以设置指定个进程同时并发执行。
八、SetPrefix设置项目名称的作用
设置项目名称主要用来区别一组定时任务,相当于分组。启动命令,查询命令,关闭命令都是对这个项目分组的任务进行操作的。假如你设置1个项目名称A,然后启动任务,再次修改项目名称为B,此时执行关闭命令是无法关闭之前启动的A项目的。
九、运行时目录和项目名称的作用
设置运行时目录主要用来保存日志、进程锁、标准输入输出信息,进程通信消息等作用。另外运行时目录和项目名称也有关联,一旦启动任务后请避免修改项目名称和运行时目录。如果需要修改任务名称和运行时目录请关闭任务再修改,否则你修改了运行时目录将无法用命令关闭运行中的任务.