<?php
/*
* This file illustrates how PHP Cron might be used. It constitutes a check in
* a database (MySQL sql source included below), and logs if the application
* runs. Here's an application overview:
*
* Purpose: To provide failover support for cron jobs on a secondary server
* Requirements: Cron, Database, command-line PHP support. Non-PHP apps can be
* wrapped in a PHP program that will exit or run and log as appropriate.
* Your crontab needs the hostname set as an environment variable so PHP can
* pick up on it. Put the following at the top of your crontab:
* HOSTNAME="hostA"
*
* SQL consists of two tables: One to define the cron jobs that are being
* monitored, a second to log events. Here is the SQL:
*
* CREATE TABLE projects (
id int(10) NOT NULL default '0',
name varchar(200) NOT NULL default '',
notes text,
cron_schedule varchar(30) NOT NULL default ''
) TYPE=MyISAM;
CREATE TABLE monitor (
id int(10) default '0',
project_id int(3) NOT NULL default '0',
event_date datetime NOT NULL default '0000-00-00 00:00:00',
event_type varchar(50) NOT NULL default '',
hostname varchar(20) default NULL,
notes text
) TYPE=MyISAM;
* I leave it to the reader to implement a front-end to add and show monitoring
* information for projects.
*
*/
include("CronParser.php");
//The project id needs to match the id of the project you enter into the projects table
$project_id = 1;
//If the host is the failover host, we check if the cron ran on the primary
if (didCronRun($project_id, "hostA") && $_ENV['HOSTNAME'] == "hostB"){
$debug_msg .= "$project cron ran on ".$_ENV['HOSTNAME']." !!!\n";
//Since the cron ran on the main host, we can exit the script.
exit;
} else {
$debug_msg .= "Hostname is set to ".$_ENV['HOSTNAME'];
//OK, the job didn't run on the primary host. Log the fact that this cron is running:
@db_log($project_id, "CRON", $_ENV['HOSTNAME']." starting my cron job");
//Now continue to run your cron application. If you're running a perl/shell script, you can just exec it
//Otherwise, you'll probably want to just set the $project_id in your
//code and include this file.
}
/**
* Utility function to determine if the cron job (id) ran normally for a
* given host.
*/
function didCronRun($id, $host){
//Implement your own db connection here.
$db = db();
//Get the schedule of the cron from the database (e.g. "0 5 * * *")
$q = "select cron_schedule from projects where id='".$id."'";
$cron_schedule = mysql_result(mysql_query($q, $db),0,0);
//Start new cron parser instance
$cron = new CronParser($cron_schedule);
$lastRan = $cron->getLastRan(); //Array (0=minute, 1=hour, 2=dayOfMonth, 3=month, 4=week, 5=year)
//Convert to Unix timestamp
$cron_ran = mktime ( $lastRan[1] ,$lastRan[0],0 , $lastRan[3] ,$lastRan[2], $lastRan[5]);
//Now, we look for a log entry for this app's cron job running OK
//We're looking for a time within 45 secs or so of the $cron_ran time.
//You may want to adjust this if your job takes a while to run...
$q = "SELECT * FROM `monitor` WHERE event_date > from_unixtime(".($cron_ran-45).") " .
" and event_type = 'CRON' " .
" and project_id='".$id."' " .
" order by event_date desc ";
$r = @mysql_query($q, $db);
$row = @mysql_fetch_array($r);
//Return either true or false depending on whether the job has run OK since given time.
if (isset($row['hostname']) && $row['hostname'] == $host){
//Job ran on the specified host
return true ;
} else {
//Job didn't run on the specified host, so it needs to run on failover host.
return false;
}
}
/**
* Log application cron event in the database
*/
function db_log($id, $type, $notes){
$logConn = db(); //Implement your own connection here
$q = "insert into monitor values ('', '".$id."', now(), '".$type."', '".$_ENV['HOSTNAME']."', '".$notes."')";
$r = @mysql_query($q, $logConn);
if (@mysql_affected_rows()< 1){
//Query seems to have failed. Email it instead:
mail ("your email", "Log failed ($type) for app id $id", $notes, "");
}
}
?>
|