#php 定时任务
代替 crontab 下执行php ,摆脱命令行控制php定时执行且无法有效融合到web前台控制执行问题,具体使用参考dome,有以下优缺点:
- linux 下子进程执行任务,所以修改脚本无需重启后台服务立即生效,windows下修改任务脚本后需重启后台脚本 但往系统添加执行不受影响
- 阻塞使用redis扩展阻塞,最低支持每秒运行一次.加上派发任务时间及默认跳过超时任务设置.所以会变成最少每2秒执行一次,可以设置不跳过超时任务,但不建议这样做.
- 任务派发及具体任务执行不在同个进程,所以windows下要启用两个后台脚本[dome/windows_main.cmd],不建议windows下使用,因为windows下执行任务在循环里,编写任务有问题或调用exit将导致后台脚本停止,linux 下为子进程执行任务,当任务脚本有问题不会统造成影响
- 可以指定运行用户,防止WEB用户跟命令行运行用户不一致导致其他问题
- 任务数据使用redis进行持久化.并使用redis的队列进行任务派发,当后台脚本挂壁后数据依托redis来保证安全.
- 执行时间语法跟crontab 类似.实现crontab的运行规则,并有辅助工具在utils种,且支持秒设置.
- 添加任务简单,只需实现 runer 接口,和实现加载runer的自动加载函数或手动引入任务类[不建议手动引入]即可.具体使用请参阅dome
- 负载问题依赖于你的redis及runer_listen.php运行数量,负载高建议在多台机器上进行任务执行[runer_listen.php]
为了效率和方便你可能需要注意此常量:
//运行多少次任务后重启执行任务子进程
//此参数仅在linux下生效
//设置true,将不使用子进程执行任务,除非任务出错[效率高点,缺点:修改代码任务代码后可能需要重启服务]
//默认为:1 每次都使用一个子进程执行任务[优点:设置的任务立即生效,无需重启服务,建议调试环境使用]
//你可以根据需求设置一定的值
define('LSYS_CRON_RUNER_LIMIT', 1);
启动服务或定义服务参数:
//示例脚本参见./dome 目录,根据你的实际需求自行定制及修改运行参数
//为了更灵活的定制,所以没用编写统一的composer命令行脚本.
//linux 下shell启动
php ./dome/unix_main.php &
//windows 下CMD启动
./dome/windows_main.cmd
自定义任务代码示例:
//添加任务
$cron = new Cron(get_redis());
//任务名,必须全局唯一,重复覆盖,可自行生成
$job_name='job_5860f54ef3ae4';//Utils::create_job_name();
//设置任务
$job= new Job($job_name,new Command("dir d:/"));
$timer= new Timer();
$timer->set_seconds(0);
$timer->set_minutes(1);
$timer->set_hours(22);
$timer->set_day(26);
$timer->set_month(12);
$timer->set_year(2016);
$job->set_timer($timer);
var_dump($cron->set_job($job));
//删除任务
$cron = new Cron(get_redis());
//任务名,必须全局唯一,可自行生成
$job_name='job_5860f54ef3ae4';//Utils::create_job_name();
var_dump($cron->del_job($job_name));
//获取待执行任务列表
$cron = new Cron(get_redis());
foreach ($cron->run_job_list() as $v){
$job=$v->get_job();
echo "任务名:".$job->get_name()."<br>";
echo "运行时间:".Utils::timer_to_string($job->get_timer())."<br>";
echo "下次运行时间:".date("Y-m-d H:i:s",$job->get_next_run_time())."<br>";
}
//获取待执行结果
$cron = new Cron(get_redis());
print_r($cron->job_result());
//实现一个具体执行,只是一个示例,实现runer接口即可,此类最好通过spl自动加载.
namespace Runer;
use LSYS\Cron\Runer;
class RunDome implements Runer{
public function run(){
//这里放你的代码
echo date("Y-m-d H:i:s")."\n";
echo "domerun\n";
flush();
}
public function serialize(){
return '';
//序列化该任务,用于存储和任务派发,当任务无附带参数,用空即可
}
public function unserialize($s){
//反序列化改任务
}
}