Планирование PHP-скриптов - PullRequest
3 голосов
/ 03 апреля 2011

Я хочу создать некоторую функцию для планирования сценариев php, например, если я хочу запустить page.php в 12.12.2012 12:12, я могу позвонить

schedule_script('12/12/2012 12:12','page.php');//or by passing a time/datetime object

или, например, вызвать одинсценарий каждую минуту

schedule_interval(60,'page.php');//every 60s=1minute

я могу добавить какую-то другую функцию, чтобы увидеть, какой сценарий запланирован, или удалить один из них.

я хочу, чтобы эти функции работали на платформах UNIX и WINDOWSЯ не хочу неприятных решений, таких как выполнение скрипта на каждой странице сайта (я хочу планировать эти команды, когда на сайте никого нет) или использование реализаций buisy wait (использование sleep () в скрипте, который проверяет, есть лилюбые запланированные задания) или что-то, что требует вмешательства пользователя (например, написать что-нибудь в консоли или открыть панель).

Я нашел команду "AT" в MSDOS (хорошо работает во всех окнах), но она очень проста, потому чтоон принимает только время, а не даты, есть более мощная версия для UNIX, но я не знаю, как ее использовать (и я хочу решение для обеих платформ).

Ответы [ 3 ]

2 голосов
/ 03 апреля 2011

Есть функция PHP, которая позволяет задерживать выполнение скрипта до определенного момента времени.

Допустим, у меня есть cron.php:

<?php

   // Usage:
   //    cron.php [interval|schedule] [script] [interval|stamp]
   if(!isset($argc) || count($argc)!=2)die; // security precaution

   $time=(int)$argv[3]; // just in case :)

   if($argv[1]=='schedule'){
       time_sleep_until((int)$_GET['until']);
       include_once($time);
   }elseif($argv[1]=='interval')
       while(true){ // this is actually an infinite loop (you didn't ask for an "until" date? can be arranged tho)
           usleep($time*1000); // earlier I said milliseconds: 1000msec is 1s, but this func is for microseconds: 1s = 1000000us
           include_once($argv[2]);
       }

?>

И ваш classes / functions файл:

// Const form K2F - Are we on windows?
define('ISWIN', strpos(strtolower(php_uname()),'win')!==false &&
                strpos(strtolower(php_uname()),'darwin')===false );

// Function from K2F - runs a shell command without waiting (works on all OSes)
function run($cmd){
    ISWIN ? pclose(popen('start /B '.$cmd,'r')) : exec($cmd.' > /dev/null &');
}

script_schedule($script,$time){
    if(is_string($time))$time=strtotime($time);
    run('php -f -- schedule '.escapeshellarg($script).' '.$time);
}

script_interval($script,$mseconds){
    run('php -f -- interval '.escapeshellarg($script).' '.$mseconds);
}

Это должно сработать. Кстати, K2F - это структура, которая воплощает ваши мечты .. быстрее. ;). Приветствия.

Редактировать: Если вам все еще нужны детали о подсчете запущенных заданий и / или их удалении (остановке), я также могу помочь с этим. Просто ответьте на мой пост, и мы продолжим.

0 голосов
/ 05 апреля 2011

Это моя реализация планировщика, мне нужно только запустить его, если он не активен, и добавить все задания в таблицу заданий mysql (у меня уже есть одно для моего основного скрипта), этот скрипт запустит все задания, готовые кбыть выполненным (таблица sql имеет поле datetime).

То, что я называю "Mutex", - это класс, который сообщает, запущена ли одна или несколько копий сценария, и может даже отправлять команды запущенному сценарию.через канал (вам просто нужно создать новый мьютекс с одинаковым именем для всех сценариев), чтобы вы могли даже остановить запущенный сценарий из другого сценария.

<?php
//---logging---
$logfile = dirname(dirname(__FILE__)).'/scheduler.log';
$ob_file = fopen($logfile,'a');
function ob_file_callback($buffer)
{
  global $ob_file;
  fwrite($ob_file,$buffer);
}




//--includes---

  $inc=dirname(dirname(__FILE__)).'/.include/';
  require_once($inc.'Mutex.php');
  require_once($inc.'jobdb.php');
//--mutex---
//i call it mutex but it's nothing like POSIX mutex,it's a way to synchronyze scripts
  $m=new Mutex('jscheduler');
  if(!$m->lock())//if this script is already running
    exit();//only one scheduler at time
//---check loop---
  set_time_limit(-1);//remove script time limit
  for(;;){
      ob_start('ob_file_callback');//logging 

     $j=jobdb_get_ready_jobs(true);//gets all ready jobs,works with mysql
     if($j!=null)//found some jobs
         foreach($j as $val){//run all jobs

            $ex='*SCRIPT NAME AND PARAMETERS HERE*';

            if(!run_script($ex))
                echo "UNABLE TO LAUNCH THE JOB!\n";
        }
     $n=($j!=null)?count($j).'JOBS LAUNCHED':'NO JOBS';


     sleep(60);
     if($m->has_to_stop())//yeah,i can stop this script from other scripts,it works with a file pipeline
        exit("# STOPPING SCHEDULER\n");            

     ob_end_flush();//LOGGING  
  }

?>

Моя функция «run_script» работает так жев качестве функции запуска «Sciberras».

Чтобы активировать планировщик, вы должны просто использовать эту команду

 run_script('scheduler.php');

, чтобы проверить, активна ли она

$m=new Mutex('jscheduler');
if(!$m->test_lock())
    echo 'SCHEDULER IS ACTIVE';
else 
    echo 'SCHEDULER IS INACTIVE';

иостановите планировщик

$m=new Mutex('jscheduler'); 
$m->ask_to_stop();//simply sent throught the pipe the command,now has_to_stop()will return true on the process that have gain the lock of the mutex
echo 'STOPPING SCHEDULER...';

Возможно, я зашел слишком далеко от его реализации, в любом случае может возникнуть проблема с "задержкой", например, если планировщик запускается в 0: 00.00 и у меня есть два scripts в 0: 01.01 и 0: 01.59 оба запускаются в 0: 02.0.Чтобы исправить это «отставание», я могу получить все задания, запланированные на следующую минуту, и запланировать их, как в коде Sciberras, используя time_sleep_until.Это не создаст слишком много запущенных потоков (я могу захотеть проверить, есть ли ограничение или падение производительности при запуске ОГРОМНОГО количества потоков, но я уверен, что будут некоторые проблемы) и обеспечить идеальное время, требующее только проверки, еслиПланировщик активен.

0 голосов
/ 03 апреля 2011
$amt_time = "1";
$incr_time = "day";
$date = "";
$now=  ''. date('Y-m-d') ."";   
if (($amt_time!=='0') && ($incr_time!=='0')) {
$date = strtotime(date("Y-m-d".strtotime($date))."+$amt_time $incr_time");
$startdate=''.date('Y-m-d',$date) ."";
} else {
$startdate="0000-00-00";
}
if ($now == $startdate) {
include ('file.php');
}

Просто предположение;) На самом деле я мог бы сделать это наоборот, но вы поняли идею

...