概述
在软件开发中,定时任务是一个常见的需求,尤其是在需要定期执行某些操作的场景中。传统的Linux cron服务虽然强大,但它的灵活性确实有限,尤其是在动态调整任务执行时间方面。但在实际项目运行中动态修改任务执行时间,实在不太灵活。
随着项目规模的扩大,管理大量的cron任务和它们的配置文件可能会变得复杂且容易出错。特别是在多环境部署的情况下,维护一致性和同步配置文件需要额外的工作。
由于cron任务的执行时间和频率是预定义的,当任务执行出现问题时,调试和跟踪可能会比较困难。特别是当任务依赖于外部系统或资源时,问题定位和解决会更加复杂。频繁修改cron配置文件可能会引入安全风险,尤其是在多用户环境中。不当的权限管理或配置错误可能会导致任务被恶意利用或执行不适当的操作。
Cron Scheduler
PHP Cron Scheduler 是一个与框架无关的cron作业调度程序,可以轻松地与您的项目集成或作为独立的命令调度程序运行。在使用这个任务调度器时,你只需要在你的服务器上创建单个 scheduler.php 入口。你的任务调度在scheduler.php方法中进行定义。
安装
composer require peppeocchi/php-cron-scheduler
开源地址:https://github.com/peppeocchi/php-cron-scheduler
如何工作
在项目根目录下创建一个包含以下内容的 scheduler.php 文件。
<?php
require_once __DIR__.'/vendor/autoload.php';
use GO\Scheduler;
// Create a new scheduler
$scheduler = new Scheduler();
// ... configure the scheduled jobs (see below) ...
// Let the scheduler execute jobs which are due.
$scheduler->run();
然后在crontab中添加一个新条目,以便每分钟运行 scheduler.php 。
* * * * * /usr/local/php-8.4/bin/php /home/tinywan/demo/scheduler.php 1>> /dev/null 2>&1
就是这样!您的调度程序已经启动并运行,现在您可以添加您的作业,而无需再担心crontab。这个Cron每分钟都会调用scheduler.php命令调度器。然后评估你的计划任务并运行到期的任务。
调度作业
默认情况下,您的所有作业将尝试在后台运行。PHP脚本和原始命令默认情况下将在后台运行,而函数将始终在前台运行。您可以通过调用 inForeground() 方法强制命令在前台运行。必须将输出发送到电子邮件的作业将在前台运行。
执行一个PHP脚本
$scheduler->php('path/to/my/script.php');
计划执行时间
有几种方法可以帮助您设置计划的执行时间。如果您不调用此方法中的任何一个,则作业将每分钟(*)运行一次。
任何表达式
at -此方法接受dragonmantank/cron-expression支持的任何表达式
$scheduler->php('script.php')->at('* * * * *');
每分钟执行
everyMinute 每分钟执行。您可以选择传递 $minute 以指定作业每 $minute 分钟运行一次。
$scheduler->php('script.php')->everyMinute();
$scheduler->php('script.php')->everyMinute(5);
每小时运行
hourly 每小时运行一次。您可以选择传递您想要运行的 $minute ,默认情况下,它将在每小时的'00'分钟运行。
$scheduler->php('script.php')->hourly();
$scheduler->php('script.php')->hourly(53);
每天运行
daily 每天运行一次。您可以选择传递 $hour 和 $minute 以获得更细粒度的控制(或字符串 hour:minute )
$scheduler->php('script.php')->daily();
$scheduler->php('script.php')->daily(22, 03);
$scheduler->php('script.php')->daily('22:03');
最佳实践
项目根目录 scheduler.php 文件参考
<?php
declare(strict_types=1);
namespace think;
date_default_timezone_set('PRC');
require __DIR__ . '/vendor/autoload.php';
# PHP 二进制文件路径
$bin = '/usr/local/php-8.4/bin/php';
$script = __DIR__ . '/think';
$scheduler = new \GO\Scheduler();
# 2024年7月16日 @add Tinywan 执行一个Linux命令
$scheduler->raw('ps aux | grep nginx');
# 2024年7月10日 @add Tinywan 订单自动取消 每1分钟执行一次
$scheduler->php($script . ' order cancel', $bin)->everyMinute(5);
$scheduler->run();
执行结果
[2024-07-28T00:10:02+08:00][info] 定时任务-商品推广关闭 end
[2024-07-28T00:11:02+08:00][info] 定时任务-账户统计 end
[2024-07-28T00:12:02+08:00][info] 定时任务-账户统计 end
[2024-07-28T00:13:01+08:00][info] 定时任务-账户统计 end
[2024-07-28T00:14:02+08:00][info] 定时任务-账户统计 end
[2024-07-28T00:15:02+08:00][info] 定时任务-商品推广关闭 start
[2024-07-28T00:15:02+08:00][info] 定时任务-订单 start
[2024-07-28T00:15:02+08:00][info] 定时任务-账户统计 end
小结
本文将探讨如何在PHP环境下实现这种动态定时任务,旨在提供一个更加灵活、安全且易于管理的定时任务执行机制。这将极大地提升项目的可扩展性和运维效率。