简介

一个强大的php层面上的定时任务调度器, 无需修改系统层面的crontab

实际中, php 结合 crontab 来实现定时任务是一种经得住考验的实践, 但每次新增/修改定时任务项时都需要去修改系统的crontab, 这会带来两个麻烦: 一个是繁琐, 一个是难以版本控制.

特点:

  • 只需维护一个crontab主作业
  • 子作业完全由PHP编写
  • 支持标准crontab的调度时间格式
  • 作业执行超时时可防止运行多个作业副本
  • 作业执行出错退出时发送邮件通知
  • 可以其他用户身份执行(若主crontab执行用户具有sudo权限)
  • 支持仅在某个主机名上运行
  • 理论上的Windows支持(包作者未测试过)

相关链接:

安装

php 5.4

composer require "hellogerard/jobby:3.4.1"

注意版本不要用3.4.1以上的, 会出问题(尽管packagist里3.4.2和3.4.3写着php>=5.4, 但实际会出问题)

php 更高版本

composer require hellogerard/jobby

配置crontab主作业

* * * * * cd /path/to/project && php jobby.php &>/dev/null

使用示例文件

cp vendor/hellogerard/jobby/resources/jobby.php .

标准使用

// 加载composer autoload
require_once __DIR__ . '/vendor/autoload.php'; // 创建Jobby实例
$jobby = new Jobby\Jobby(); // 每个job都有一个唯一名称
$jobby->add('CommandExample', [ // 运行一个shell命令
'command' => 'ls', // 运行一个闭包(与 'command' 互斥)
//'closure' => function() {
// echo "I'm a function!\n";
// return true;
//}, // 支持通用调度配置
'schedule' => '0 * * * *', // 可使用日期时间字符串
//'schedule' => '2017-05-03 17:15:00', // 使用闭包返回boolean来确定是否执行
//'schedule' => function(DateTimeImmutable $now) {
// // Run on even minutes
// return $now->format('i') % 2 === 0;
//}, // 标准输出/标准错误会写入到指定日志文件
'output' => 'logs/command.log', // 临时关闭某个任务
'enabled' => false,
]); $jobby->run();

选项

每个任务的必须选项

Key Type Description
schedule string Crontab schedule format (man -s 5 crontab) or DateTime format (Y-m-d H:i:s) or callable (function(): Bool { /* ... */ })
command string The shell command to run (exclusive-or with closure)
closure Closure The anonymous PHP function to run (exclusive-or with command)

以下的选项列表可应用于单个任务或全局任务(通过传入 Jobby构造器).

全局选项将会作为每个任务的默认配置, 单个任务可覆盖全局选项.

Option Type Default Description
runAs string null Run as this user, if crontab user has sudo privileges
debug boolean false Send jobby internal messages to 'debug.log'
Filtering 过滤 Options to determine whether the job should run or not
environment string null or getenv('APPLICATION_ENV') Development environment for this job
runOnHost string gethostname() Run jobs only on this hostname
maxRuntime integer null Maximum execution time for this job (in seconds)
enabled boolean true Run this job at scheduled times
haltDir string null A job will not run if this directory contains a file bearing the job's name
Logging 日志 Options for logging
output string /dev/null Redirect stdout and stderr to this file
output_stdout string value from output option Redirect stdout to this file
output_stderr string value from output option Redirect stderr to this file
dateFormat string Y-m-d H:i:s Format for dates on jobby log messages
Mailing 邮件 Options for emailing errors
recipients string null Comma-separated string of email addresses
mailer string sendmail Email method: sendmail or smtp or mail
smtpHost string null SMTP host, if mailer is smtp
smtpPort integer 25 SMTP port, if mailer is smtp
smtpUsername string null SMTP user, if mailer is smtp
smtpPassword string null SMTP password, if mailer is smtp
smtpSecurity string null SMTP security option: ssl or tls, if mailer is smtp
smtpSender string jobby@ The sender and from addresses used in SMTP notices
smtpSenderName string Jobby The name used in the from field for SMTP messages

项目实践

项目存在多个不同游戏服, 且每个服使用的配置文件不一样, 因此执行定时任务时需对每个服单独执行, 特创建crontab.php 文件用于针对不同服分别调用 jobby.php

crontab配置

* * * * * cd /path/to/project && php crontab.php &>/dev/null

crontab.php

<?php
// 服务器列表, 实际是从其他地方读取的
$servers = ["s1", "s2", "s3", "s4"];
foreach ($servers as $server) {
$cmd = sprintf("php jobby.php %s &>/dev/null &", $server);
exec($cmd);
var_dump(compact('cmd'));
}

jobby.php

<?php
// 环境配置
// ... $server = $argv[1]; $cmdPrefix = "php dispatcher.php $server "; $jobby = new \Jobby\Jobby([
'output' => "具体的日志输出文件路径",
]);
$jobs = require("jobby_config.php");
foreach ($jobs as $name => $job) {
if (isset($config['command'])) {
$config['command'] = $cmdPrefix.$config['command'];
}
$jobby->add($name, $job);
}
$jobby->run();

jobby_config.php

<?php
return [
"check_index" => [
'command' => "month_check_index",
'schedule' => '30 5 1 * *',
'maxRuntime' => 600,
], 'minute_stats' => [
'command' => "minute_stats",
'schedule' => '* * * * *',
'maxRuntime' => 300,
'enabled' => true,
],
];

dispatcher.php 加载具体服的具体环境, 并调用实际要运行的php定时任务代码

$server = $argv[1];
$command = $argv[2]; // 加载具体服的环境配置
// ... // 执行具体定时任务代码(此处忽略异常处理)
require __DIR__ . DIRECTORY_SEPARATOR . "jobs" . DIRECTORY_SEPARATOR . $command . ".php";

jobs/month_check_index.php

<?php
// 具体任务

jobs/minute_stats.php

<?php
// 具体任务

[原创]php任务调度器 hellogerard/jobby的更多相关文章

  1. TaskScheduler一个.NET版任务调度器

    TaskScheduler是一个.net版的任务调度器.概念少,简单易用. 支持SimpleTrigger触发器,指定固定时间间隔和执行次数: 支持CronTrigger触发器,用强大的Cron表达式 ...

  2. 21 BasicTaskScheduler基本任务调度器(一)——Live555源码阅读(一)任务调度相关类

    21_BasicTaskScheduler基本任务调度器(一)——Live555源码阅读(一)任务调度相关类 BasicTaskScheduler基本任务调度器 BasicTaskScheduler基 ...

  3. 18 TaskScheduler任务调度器抽象基类——Live555源码阅读(一)任务调度相关类

    这是Live555源码阅读的第二部分,包括了任务调度相关的三个类.任务调度是Live555源码中很重要的部分. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/ol ...

  4. azkaben任务调度器

    azkaban学习笔记总结 01.工作流调度器azkaban 1. 任务调度概述 一个完整的数据分析系统通常都是由大量任务单元组成: shell脚本程序,java程序,mapreduce程序.hive ...

  5. SpringBoot2 task scheduler 定时任务调度器四种方式

    github:https://github.com/chenyingjun/springboot2-task 使用@EnableScheduling方式 @Component @Configurabl ...

  6. Spark源码剖析 - SparkContext的初始化(五)_创建任务调度器TaskScheduler

    5. 创建任务调度器TaskScheduler TaskScheduler也是SparkContext的重要组成部分,负责任务的提交,并且请求集群管理器对任务调度.TaskScheduler也可以看作 ...

  7. C# 可指定并行度任务调度器

    可指定并行度的任务调度器 https://social.msdn.microsoft.com/Forums/zh-CN/b02ba3b4-539b-46b7-af6b-a5ca3a61a309/tas ...

  8. springMVC + quartz实现定时器(任务调度器)

    首先我们要知道任务调度器(定时器)有几种,这边我会写三种 第一种是基于JDK的本身的一个定时器(优点:简单,缺点:满足不了复杂的需求) package com.timer1; import java. ...

  9. 基于Spring Task的定时任务调度器实现

    在很多时候,我们会需要执行一些定时任务 ,Spring团队提供了Spring Task模块对定时任务的调度提供了支持,基于注解式的任务使用也非常方便. 只要跟需要定时执行的方法加上类似 @Schedu ...

随机推荐

  1. Photoshop中的高斯模糊、高反差保留和Halcon中的rft频域分析研究

    在Halcon的rft变换中,我们经常可以看到这样的算子组合: rft_generic (Image, ImageFFT2, 'to_freq', 'none', 'complex', Width) ...

  2. code1001 舒适的路线

    n次最小生成树kruskal 将所有的边排序,权值小的在前. 设排序后第i条边为路径中的最长边,那么这条路径一定是由1~i中的一些边组成 因为最高速和最低速的差尽量小,最高速确定了,最低速应尽量大. ...

  3. DataStage 错误集(持续更新)

    DataStage 错误集(持续更新) DataStage序列文章 DataStage 一.安装 DataStage 二.InfoSphere Information Server进程的启动和停止 D ...

  4. js的prototype(2)

    1 原型法设计模式 在.Net中可以使用clone()来实现原型法 原型法的主要思想是,现在有1个类A,我想要创建一个类B,这个类是以A为原型的,并且能进行扩展.我们称B的原型为A. 2 javasc ...

  5. Devexpress + wcf +ef 批量更新处理

    项目结构: 1.客户端:Winform, 2.数据访问:EF4.0(从数据库生成模型-懒人必需这样) 3.DTO:直接使用EF实体 4.服务端:WCF 托管在IIS中采用basicHttp帮定(这样可 ...

  6. HDU 5120 Intersection (圆的面积交)

    题意:给定两个圆环,求两个圆环的面积交. 析:很容易知道,圆环面积交就是,大圆与大圆面积交 - 大圆和小圆面积交 - 小圆和大圆面积交 + 小圆和小圆面积交. 代码如下: #pragma commen ...

  7. javascript 区分对象类型

    在 JavaScript 里使用 typeof 来判断数据类型,只能区分基本类型,即 “number”,”string”,”undefined”,”boolean”,”object” 五种.对于数组. ...

  8. winform 开发中 把耗时操作 封装起来 异步执行(.net 4.0)

    .先定义一个 BackgroundTask.cs 代码如下: public class BackgroundTask { private static WaitDialogForm LoadingDl ...

  9. xaml mvvm(2)之属性绑定

    通过微软INotifyPropertyChanged接口,可以实现对UI实时更新,不管是数据源或者目标对象,可以实现相互通知. 下面我们根据INotifyPropertyChanged编写一个扩展类. ...

  10. Python2.4+ 与 Python3.0+ 主要变化与新增内容

    Python2                          Python3print是内置命令                 print变为函数print >> f,x,y     ...