nirmit/crunzplus

Crunz from Lavary - 更强大!直接在代码中安排任务。

v1.0 2017-01-05 14:56 UTC

This package is not auto-updated.

Last update: 2024-09-28 20:48:22 UTC


README

一次性安装cron作业,从代码中管理其余部分。

Version Build

Crunz是一个框架无关的包,用于通过流畅的API在PHP中安排周期性任务(cron作业)。

Crunz能够执行任何类型的可执行命令以及PHP闭包。

安装

要安装它

composer require lavary/crunz

如果安装成功,将一个名为crunz的命令行实用程序符号链接到您项目的vendor/bin目录。

它是如何工作的?

想法非常简单:我们不是在crontab文件中安装cron作业,而是使用Crunz接口在单个或多个PHP文件中定义它们。

以下是一个基本示例

<?php
// tasks/backupTasks.php

use Crunz\Schedule;

$schedule = new Schedule();
$schedule->run('cp project project-bk')       
         ->daily();

return $schedule;

要运行任务,您只需要安装一个普通的cron作业(一个crontab条目),该作业每分钟运行一次,并将责任委托给Crunz的事件运行器

* * * * * /project/vendor/bin/crunz schedule:run

schedule:run命令负责收集所有PHP任务文件并运行到期的任务。

任务文件

任务文件类似于crontab文件。就像crontab文件一样,它们可以包含一个或多个任务。

通常我们在项目的根目录中的tasks/目录内创建我们的任务文件。

默认情况下,Crunz假设所有任务文件都位于项目根目录中的tasks/目录内。

有两种指定源目录的方法:1)配置文件 2)作为事件运行器命令的参数。

我们可以通过将参数传递给事件运行器来显式设置源路径

* * * * * /project/vendor/bin/crunz schedule:run /path/to/tasks/directory

创建一个简单的任务

在终端中,切换到您的项目根目录,并运行以下命令

mkdir tasks && cd tasks
nano GeneralTasks.php

然后,添加以下任务

<?php
// tasks/FirstTasks.php

use Crunz\Schedule;

$schedule = new Schedule();

$schedule->run('cp project project-bk')       
         ->daily()
         ->description('Create a backup of the project directory.');

// ...

// IMPORTANT: You must return the schedule object
return $schedule; 

创建任务文件有一些约定,您需要遵守。首先,文件名应以Tasks.php结尾,除非我们通过配置设置更改此设置。

此外,我们必须在每个文件结束时返回Schedule类的实例,否则事件运行器将跳过文件中的所有任务。

由于Crunz递归地扫描任务目录,我们可以将所有任务放在一个文件中,或者根据它们的用途放在不同的文件(或目录)中。这种行为有助于我们拥有一个井井有条的任务目录。

命令

我们可以使用run()运行任何命令或脚本。此方法接受两个参数:要执行的命令和(如果有)命令选项(作为关联数组)。

普通命令或脚本

<?php
use Crunz\Schedule;

$schedule = new Schedule();

$schedule->run('/usr/bin/php backup.php', ['--destination' => 'path/to/destination'])       
         ->everyMinute()
         ->description('Copying the project directory');
         
return $schedule;

在上面的示例中,--destinationbackup.php脚本支持的一个选项。

闭包

我们也可以写一个闭包来代替命令

<?php
use Crunz\Schedule;

$schedule = new Schedule();

$x = 12;
$schedule->run(function() use ($x) { 
   // Do some cool stuff in here 
})       
->everyMinute()
->description('Copying the project directory');
         
return $schedule;

执行频率

有各种方法可以指定任务应该何时以及多久运行一次。我们可以将这些方法组合起来,以获得所需的时间间隔。

时间单位

有一组方法指定时间单位(大于分钟)作为频率。它们通常以ly后缀结尾,如hourly()daily()weeklymonthly()quarterly()yearly

<?php
// ...
$schedule->run('/usr/bin/php backup.php')       
         ->daily();
// ...

上面的任务将在午夜每天运行一次。

这里还有一个,它是在每月的第一天运行的。

<?php
// ...
$schedule->run('/usr/bin/php email.php')       
         ->monthly();
// ...

使用这一组方法安排的所有事件都发生在那个时间单位的开始。例如,weekly()将在周日运行事件,而monthly()将在每月的第一天运行。

动态方法

动态方法可以在运行时提供广泛的频率选项。我们只需遵循以下模式

every[NumberInCamelCaseWords]Minute|Hour|Day|Months?

如我们所见,方法应以单词every开头,后跟驼峰式命名的数字,以以下时间单位之一结尾:分钟、小时、天和月

末尾的s是可选的,只是为了语法。

话虽如此,以下方法是有效的

  • everyFiveMinutes()
  • everyMinute()
  • everyTwelveHours()
  • everyMonth
  • everySixMonths()
  • everyFifteenDays()
  • everyFiveHundredThirtySevenMinutes()
  • everyThreeThousandAndFiveHundredFiftyNineMinutes()
  • ...

这是在任务文件中使用的方法

<?php
// ...

$schedule->run('/usr/bin/php email.php')       
         ->everyTenDays();

$schedule->run('/usr/bin/php some_other_stuff.php')       
         ->everyThirteenMinutes();
// ...

return $schedule;

在特定时间运行事件

要安排一次性任务,可以使用on()方法,如下所示

<?php
// ...
$schedule->run('/usr/bin/php email.php')       
         ->on('13:30 2016-03-01');
// ...

上述任务将在2016年3月1日下午1:30运行。

On()接受PHP的strtotime函数解析的任何日期格式。

要指定时间,我们使用at()方法

<?php
// ...
$schedule->run('/usr/bin/php script.php')       
         ->daily()
         ->at('13:30');
// ...

我们还可以使用dailyAt()得到相同的结果

<?php
// ...
$schedule->run('/usr/bin/php script.php')       
         ->dailyAt('13:30');
// ...

如果我们只向on()方法传递时间,它将产生与使用at()相同的效果

<?php
// ...
$schedule->run('/usr/bin/php email.php')       
         ->mondays()
         ->on('13:30');
         
// is the sames as
$schedule->run('/usr/bin/php email.php')       
         ->mondays()
         ->at('13:30');
// ...

工作日

Crunz还提供了一套方法,用于指定一周中的某一天。这些方法被设计成用作约束,不应单独使用。原因是工作日方法仅修改cron作业表达式的“星期几”字段。

考虑以下示例

<?php
// Cron equivalent:  * * * * 1
$schedule->run('/usr/bin/php email.php')       
         ->mondays();

乍一看,这个任务似乎在每个星期一运行,但由于它只修改了cron作业表达式的“星期几”字段,因此任务在每个星期一每分钟运行。

这是使用工作日方法的正确方式

<?php
// ...
$schedule->run('/usr/bin/php email.php')       
         ->everyThreeHours()
         ->mondays();
// ...

在上面的任务中,我们使用mondays()作为约束,以在星期一每三个小时运行任务。

设置单个字段

Crunz的方法不仅限于前面解释的现成方法。我们还可以设置单个字段以创建自定义频率。这些方法可以接受一个值数组,或者使用逗号分隔的列表参数

<?php
// ...
$schedule->run('/usr/bin/php email.php')       
         ->minute(['1-30', 45, 55])
         ->hour('1-5', 7, 8)
         ->dayOfMonth(12, 15)
         ->month(1);

或者

<?php
// ...
$schedule->run('/usr/bin/php email.php')       
         ->minute('30')
         ->hour('13')
         ->month([1,2])
         ->dayofWeek('Mon', 'Fri', 'Sat');

// ...

经典方法

我们也可以像在crontab文件中一样使用旧方法进行调度

<?php
$schedule->run('/usr/bin/php email.php')
         ->cron('30 12 * 5-6,9 Mon,Fri');     
        

根据我们的用例,我们可以选择和组合适当的工具集,这些工具集更容易使用。

更改目录

您可以使用in()方法在运行命令之前更改目录

<?php

// ...

$schedule->run('./deploy.sh')
         ->in('/home')
         ->weekly()
         ->sundays()
         ->at('12:30')
         ->appendOutputTo('/var/log/backup.log');

// ...

return $schedule;

任务生命周期

在crontab条目中,我们无法轻松地指定任务的寿命(任务活跃的时间段)。然而,在Crunz中,这已经变得简单了

<?php
//
$schedule->run('/usr/bin/php email.php')
         ->everyFiveMinutes()
         ->from('12:30 2016-03-04')
         ->to('04:55 2016-03-10');
 //       

或者我们可以使用between()方法得到相同的结果

<?php
//
$schedule->run('/usr/bin/php email.php')
         ->everyFiveMinutes()
         ->between('12:30 2016-03-04', '04:55 2016-03-10');

 //       

如果我们不指定日期部分,任务将每天活跃,但仅限于指定的持续时间

<?php
//
$schedule->run('/usr/bin/php email.php')
         ->everyFiveMinutes()
         ->between('12:30', '04:55');

 //       

上述任务每天在下午12:30到下午4:55之间每五分钟运行。

运行条件

在传统的crontab文件中,我们无法轻松地为任务设置条件。但是,通过when()skip()方法,这已经变得容易了。

考虑以下代码

<?php
//
$schedule->run('/usr/bin/php email.php')
         ->everyFiveMinutes()
         ->between('12:30 2016-03-04', '04:55 2016-03-10')
         ->when(function() {
           if ($some_condition_here) { return true; }
         });

 //       

方法 when() 接受一个回调函数,该回调函数必须返回 TRUE 才能执行任务。当我们需要在执行资源密集型任务之前检查资源时,这非常有用。

我们还可以使用 skip() 方法在某些条件下跳过任务。如果传入的回调函数返回 TRUE,则任务将被跳过。

<?php
//
$schedule->run('/usr/bin/php email.php')
         ->everyFiveMinutes()
         ->between('12:30 2016-03-04', '04:55 2016-03-10')
         ->skip(function() {
             if ($some_condition_here) { return true; }  
    });

 //       

对于单个任务,我们可以多次使用这些方法。它们按顺序进行评估。

配置

Crunz 以 YAML 格式提供了一些配置选项。为了修改配置设置,强烈建议保留配置文件的副本,而不是修改原始文件。

要创建配置文件的副本,首先我们需要发布配置文件

/project/vendor/bin/crunz publish:config
The configuration file was generated successfully

因此,配置文件的副本将在我们的项目根目录中创建。

配置文件看起来像这样

# Crunz Configuration Settings

# This option defines where the task files and
# directories reside.
# The path is relative to the project's root directory,
# where the Crunz is installed (Trailing slashes will be ignored).
source: tasks

# The suffix is meant to target the task files inside the ":source" directory.
# Please note if you change this value, you need
# to make sure all the existing tasks files are renamed accordingly.
suffix: Tasks.php

# By default the errors are not logged by Crunz
# You may set the value to true for logging the errors
log_errors: false

# This is the absolute path to the errors' log file
# You need to make sure you have the required permission to write to this file though.
errors_log_file:

# By default the output is not logged as they are redirected to the
# null output.
# Set this to true if you want to keep the outputs
log_output: false

# This is the absolute path to the global output log file
# The events which have dedicated log files (defined with them), won't be
# logged to this file though.
output_log_file:

# This option determines whether the output should be emailed or not.
email_output: false

# This option determines whether the error messages should be emailed or not.
email_errors: false

# Global Swift Mailer settings
#
mailer:
    # Possible values: smtp, mail, and sendmail
    transport: smtp
    recipients:
    sender_name:
    sender_email:


# SMTP settings
#
smtp:
    host:
    port:
    username:
    password:
    encryption:

如您所见,有几个选项,如 source,用于指定源任务目录。其他选项用于错误/输出记录/电子邮件目的。

每次运行 Crunz 命令时,它都会查看项目的根目录,以查看是否存在任何用户修改的配置文件。如果配置文件不存在,它将使用随包一起提供的配置文件。

并行和锁定机制

Crunz 并行(在单独的进程)运行计划事件,因此具有相同执行频率的所有事件将异步同时运行。为了实现这一点,Crunz 使用 symfony/Process 库在子进程中运行任务。

如果一个任务的执行持续到下一个间隔甚至更长时间,我们称同一实例的任务是重叠的。在某些情况下,这不会成问题,但在某些情况下,这些任务正在修改数据库数据或文件,这可能会引起意外的行为,甚至数据丢失。

为了防止关键任务相互重叠,Crunz 通过 preventOverlapping() 方法提供锁定机制,该机制确保如果前一个实例正在运行,则不会运行任何任务。

<?php
//
$schedule->run('/usr/bin/php email.php')
         ->everyFiveMinutes()
         ->preventOverlapping();
 //       

保留输出

计划任务通常有输出,这些输出通常通过电子邮件发送给 crontab 文件的所有者,或者 crontab 文件内通过 MAILTO 环境变量设置的用户或用户组。

我们还可以使用 >>> 运算符将标准输出重定向到物理文件

* * * * * /command/to/run >> /var/log/crons/cron.log

Crunz 已自动化了这类操作。要将每个事件的输出自动发送到日志文件,我们可以在配置文件中相应地设置 log_outputoutput_log_file 选项

# Configuration settings

## ...
log_output:      true
output_log_file: /var/log/crunz.log
## ...

这会将事件的输出(如果执行成功)发送到 /var/log/crunz.log 文件。但是,我们需要确保我们有权限写入相应的文件。

如果我们需要按事件记录输出,我们可以像这样使用 appendOutputTo()sendOutputTo() 方法

<?php
//
$schedule->run('/usr/bin/php email.php')
         ->everyFiveMinutes()
         ->appendOutputTo('/var/log/crunz/emails.log');

 //       

方法 appendOutputTo() 追加 输出到指定的文件。要每次运行后用新数据覆盖日志文件,我们使用 saveOutputTo() 方法。

还可以通过在配置文件中设置 email_outputmailer 设置,将错误作为电子邮件发送到一组收件人。

错误处理

Crunz 通过记录和允许添加一组错误回调来简化错误处理。

错误回调

您可以设置任意数量的回调,以便在发生错误时运行

<?php

use Crunz\Schedule;
$schedule = new Schedule();

$schedule->add('command/to/run')
         ->everyFiveMinutes();

$schedule
->onError(function(){
   // Send mail
})
->onError(function(){
   // Do something else
});

return $schedule;

如果发生错误,将执行两个定义的回调。

错误记录

为了记录每次运行过程中可能出现的错误,我们可以在配置文件中设置log_errorerror_log_file配置,如下所示

# Configuration settings

# ...
log_errors:      true
errors_log_file: /var/log/error.log
# ...

因此,如果由于某些原因事件执行失败,错误信息将被追加到指定的错误日志文件中。每个条目都提供了有用的信息,包括发生时间、事件描述、导致错误的执行命令以及错误信息本身。

通过在配置文件中设置email_errormailer配置,也可以将错误作为电子邮件发送给一组收件人。

预处理和后处理钩子

有时候,我们想在事件前后执行某些操作。通过将预处理和后处理回调附加到相应的事件上,这是可以实现的。

为此,我们在EventSchedule对象上使用before()after(),这意味着我们可以在事件级别以及调度级别上设置预和后钩子。与调度绑定的钩子将在所有事件之前运行,在所有事件完成后运行。

<?php
// ...

$schedule = new Schedule();

$schedule->run('/usr/bin/php email.php')
         ->everyFiveMinutes()
         ->before(function() { 
             // Do something before the task runs
         })
         ->before(function() { 
                 // Do something else
         })
         ->after(function() {
             // After the task is run
         });
 
$schedule

->before(function () {
   // Do something before all events
})
->after(function () {
   // Do something after all events are finished
}
->before(function () {
   // Do something before all events
});

//  ...   

我们可能需要多次使用这些方法,可以通过链式调用它们。

只有当事件的执行成功时,才会调用后执行回调。

其他有用命令

我们已经使用了一些crunz命令,如schedule:runpublish:config

要查看crunz的所有有效选项和参数,我们可以运行以下命令

vendor/bin/crunz --help

列出任务

其中这些命令之一是crunz schedule:list,它以表格格式列出定义的任务(在收集的*.Tasks.php文件中)。

vendor/bin/crunz schedule:list

+---+---------------+-------------+--------------------+
| # | Task          | Expression  | Command to Run     |
+---+---------------+-------------+--------------------+
| 1 | Sample Task   | * * * * 1 * | command/to/execute |
+---+---------------+-------------+--------------------+

生成任务

还有一个名为make:task的有用命令,它可以生成包含所有默认值的任务文件骨架,因此我们不必从头开始编写它们。我们可以根据我们的需求稍后修改输出文件。

例如,要创建一个每小时在星期一运行/var/www/script.php的任务,我们运行以下命令

vendor/bin/crunz make:task exampleOne --run scripts.php --in /var/www --frequency everyHour --constraint mondays
Where do you want to save the file? (Press enter for the current directory)

运行此命令时,Crunz会询问我们想要保存文件的路径。默认情况下,它是在我们的源任务目录。

因此,事件被定义在指定任务目录内的一个名为exampleOneTasks.php的文件中。

要查看事件是否已成功创建,我们可以列出事件

crunz schedule:list

+---+------------------+-------------+----------------+
| # | Task             | Expression  | Command to Run |
+---+------------------+-------------+----------------+
| 1 | Task description | 0 * * * 1 * | scripts.php    |
+---+------------------+-------------+----------------+

要查看make:task命令的所有选项及其默认值,我们可以运行此

vendor/bin/crunz make:task --help

如果您需要帮助

请使用GitHub问题提交所有问题和疑问,我将尽力帮助您。

许可证

Crunz是在MIT许可证条款下免费分发的软件。