4

I want to create some function to schedule php scripts,for example if i want tu run page.php at 12/12/2012 12:12 i can call

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

or for example call one script every minute

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

i'll may add some other function to see what script are scheduled or delete one of them.

i want this functions to work on both UNIX and WINDOWS platforms,i DO NOT want ugly solutions like executing a script on every page of the site(i want to schedule this commands when nobody is on the site) or using "buisy wait" implementations ( using sleep() on a script that checks if there are any scheduled jobs) or something that require user intervention(like write something in console or open a panel).

I found the "AT" command on MSDOS(works well on all windows)but it's very basic because it accept only time and not dates,there's a more powerful version on UNIX but i don't know how to use it(and i want a solution for both platforms).

Plokko
  • 723
  • 2
  • 10
  • 23
  • 1
    What about crons? That's what they're there for. Windows got something similar afaik. – Eliasdx Apr 03 '11 at 00:03
  • 1
    Its called "task" under windows, as far as I remember. – KingCrunch Apr 03 '11 at 00:06
  • A Cron job for unix and schedule tasks in windows. Then it's up to you what the script should do. – heldt Apr 03 '11 at 00:07
  • 2
    I think he means he wants to be able to call this command from within a PHP script and it should create a cron job, or Windows scheduled task, for him. – Hammerite Apr 03 '11 at 00:08
  • At least for *nix systems there is no problem to set up a cron job with a php script. I can imagine its similar under windows. – KingCrunch Apr 03 '11 at 00:29
  • @KingCrunch it's EXACTLY what i want to do,i prefer system function but i want to call it with a php function(i've included some possible functions and examples)and works on both windows and unix. – Plokko Apr 05 '11 at 18:59

3 Answers3

3

There's a PHP function which lets you delay script execution till a point in time.

So let's say I have 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]);
       }

?>

And your classes/functions file:

// 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);
}

It ought to work. By the way, K2F is this framework that makes your dreams come true..faster. ;). Cheers.

Edit: If you still want the parts about counting running jobs and/or deleting(stopping) them, I can help you out with it as well. Just reply to my post and we'll follow up.

Christian
  • 27,509
  • 17
  • 111
  • 155
  • that's like a "buisy wait" but it's not a bad idea. Anyway i have created a similar solution creating a MUTEX (it works between scripts,it's NOT LOCKING even on windows(you still have the option to make it wait)like the cheap flock in php)and it can recover from errors. I created a scheduler script,a function run_script() that launches any script like exec but without waiting. The scheduler simply lock the mutex on start or exit if it's locked(so i have ONLY ONE scheduler active) and make a loop every 60s to check the job db and launch all ready jobs. i have only to launch the schedule once. – Plokko Apr 03 '11 at 13:44
  • i'll post my solution later,your solution is good but have a problem: if the server is restarted ALL jobs will be stopped and for each job scheduled php must open one "thread". in my solution i have only one thread and you only have to check if the lock is inactive and if it's inactive you simply have to launch the scheduler. Anyway if someone has a better idea please post it. – Plokko Apr 03 '11 at 13:47
  • If the server restarts, all jobs will have to restart in your case as well. As to threads, if you are loading a (different) PHP file for each job, there needs to be a different thread, whether you like it or not. I don't exactly understand your solution of using a mutex, since that's mostly a way to ensure running something once while being able to communicate with it - something I overlooked in my code since I didn't see it as the primary scope of your question. – Christian Apr 03 '11 at 22:31
  • your code is perfect and i'll use part of it to improve my scripts,anyway my idea was to have a single schedule process that works like CRON checking if some jobs are ready and launch them so i have only one process idling for the schedule(it checks(and execute) and sleeps for 60s). I implemented it in this way because i'm planning to schedule a huge number of jobs,otherwise your implementation would be great. If someone can do it only with system command(if it's not a security/permission problem)please post it. – Plokko Apr 04 '11 at 17:55
1

This is my implementation of the scheduler,i need only to launch it if isn't active and add all jobs on the mysql job table(i already have one for my main script),this script will launch all jobs ready to be executed(the sql table have a datetime field).

What i call "Mutex" is a class that tells if one or more than one copy of the script is running and can even send commands to the running script throught a pipe(you simply have to create a new mutex with the same name for all the scripts)so you can even stop a running script from another script.

<?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  
  }

?>

My "run_script" function works the same way as the Sciberras "run" function.

To activate the scheduler you should simply use this command

 run_script('scheduler.php');

to check if it's active

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

and to stop the scheduler

$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...';

i may have gone way too far on his implementation,anyway there may be a problem of "lag",for example if the scheduler starts at 0:00.00 and i have two scripts at 0:01.01 and 0:01.59 both are launched at 0:02.0 . To fix this "lag" i'll may retreive all the jobs scheduled in the next minute and schedule them like in the Sciberras code using time_sleep_until. This will not create too many running threads(i may want to test if there's a limit or a performance drop on launching a HUDGE amount of threads but i'm sure there will be some problems)and ensures perfect timing requiring only to check if the scheduler is active.

Plokko
  • 723
  • 2
  • 10
  • 23
0
$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');
}

Just a guess ;) Actually I might have it in reverse but you get the idea

M2D 4YH
  • 5
  • 4
  • please use a function format like the ones i used in the example,also the scripts are known to be VERY HEAVY so i cannot use include – Plokko Apr 03 '11 at 13:42