fake cron

Coding Critique is the place to post source code for peer review by other members of DevNetwork. Any kind of code can be posted. Code posted does not have to be limited to PHP. All members are invited to contribute constructive criticism with the goal of improving the code. Posted code should include some background information about it and what areas you specifically would like help with.

Popular code excerpts may be moved to "Code Snippets" by the moderators.

Moderator: General Moderators

User avatar
s.dot
Tranquility In Moderation
Posts: 5001
Joined: Sun Feb 06, 2005 7:18 pm
Location: Indiana

fake cron

Post by s.dot »

Some topic earlier referred to the usage of crons, and it was doubted weather or not he/she had access to cron jobs.

And I know some people don't, or some people can create a limited number of cron jobs when they need more. So I made this "fake cron" class.. maybe it might work. I haven't tested it, but theoretically in my head it should work. I have doubts about the usage of include(). You guys can tell me what you think. =]

fakecron.class.php

Code: Select all

<?php

class fakeCron
{
	/*
	** Container for cronjobs stored in the format [time] => script
	*/
	private $_cronJobs = array();

	/*
	** The amount of time to wait before checking if a script needs to be run
	*/
	private $_timeout = 60;

	/*
	** Method to set the number of seconds between checking if the script needs
	** to run.
	** @param int $time (in seconds)
	** @access public
	*/
	public function setTimeout($time)
	{
		$this->_timeout = $time;
	}

	/*
	** Method to add a script and time to run to the cronJobs array.
	** @param string $script (script to be executed)
	** @param mixed $timeToRun (any time format that can be converted to a timestamp
	** using strtotime())
	** @access public
	*/
	public function addCron($script, $timeToRun)
	{
		if (is_array($timeToRun)) {
			foreach ($timeToRun AS $timeEach)
			{
				$this->_addCron($script, $timeEach);
			}
		} else
		{
			$this->_addCron($script, $timeToRun);
		}
	}
	
	/*
	** Internal method to add to $this->_cronJobs array
	** @access private
	*/
	private function _addCron($script, $timeToRun)
	{
		if (strtotime($timeToRun) !== false) {
			$this->_cronJobs[strtotime($timeToRun)] = $script;
		} else {
			trigger_error('FakeCron: Could not parse time (' . $timeToRun . ') given for script ('
				 . $script . ') into timestamp', E_USER_ERROR);
		}
	}

	/*
	** This method sets the script so it will run hypothetically forever and
	** starts an infinite loop, checking if any scripts need to be run and then
	** sleep()ing.
	** @access public
	*/
	public function run()
	{
		ignore_user_abort(true);
		set_time_limit(0);

		while (true)
		{
			foreach ($this->_cronJobs AS $k => $v)
			{
				if (($k <= time()) && ($k >= time()-$this->_timeout)) {
					include $v;
				}
			}

			$this->checkKill();
			
			sleep($this->_timeout);
		}
	}
	
	/*
	** Method to check for existence of kill.txt
	** If found, the script will exit.
	*/
	private function _checkKill()
	{
		if (file_exists('kill.txt')) {
			if (!unlink('kill.txt')) {
				die('Fake Cron: kill.txt was found and could not be deleted.  Fake Cron '
					. 'was successfully killed, but will not be able to run in the future.  Change '
					. 'permissions on kill.txt or manually delete it.');
			}
			
			exit;
		}
	}
}
Example

Code: Select all

$fakeCron = new fakeCron();
$fakeCron->addCron('updatestats.php', '12:30 AM');  //runs at 12:30 AM every day
$fakeCron->addCron('sendmailinglist.php', '1 PM');  //runs at 1 PM every day

//runs on specific time on specific date
$fakeCron->addCron('somecron.php', 'Saturday Aug 26, 2007 3:15 AM');

//runs on each time of array of times every day
$fakeCron->addCron('updatestatsagain.php', array('1 PM', '2 PM', '3 PM', '1 AM', '2 AM', '3 AM'));

$fakeCron->run();
To kill fake cron (to update cronjobs list). Manually create kill.txt or write a script to create it. Fake cron will detect it, kill the script, and then delete the file so fake cron can run again.
Last edited by s.dot on Thu Aug 16, 2007 11:18 am, edited 3 times in total.
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.
User avatar
VladSun
DevNet Master
Posts: 4313
Joined: Wed Jun 27, 2007 9:44 am
Location: Sofia, Bulgaria

Post by VladSun »

It would be nice if it accepts crontab time format ;)
There are 10 types of people in this world, those who understand binary and those who don't
User avatar
VladSun
DevNet Master
Posts: 4313
Joined: Wed Jun 27, 2007 9:44 am
Location: Sofia, Bulgaria

Post by VladSun »

Also, one should be able to add/remove cron jobs in real time.
There are 10 types of people in this world, those who understand binary and those who don't
User avatar
s.dot
Tranquility In Moderation
Posts: 5001
Joined: Sun Feb 06, 2005 7:18 pm
Location: Indiana

Post by s.dot »

Not sure what you mean in real time?
Also, do you presume it would work? I'd test it.. but I really have nothing to test it on. Guess I could make some stuff to test it on.
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.
User avatar
VladSun
DevNet Master
Posts: 4313
Joined: Wed Jun 27, 2007 9:44 am
Location: Sofia, Bulgaria

Post by VladSun »

scottayy wrote:Not sure what you mean in real time?
I mean that after you request this PHP file and run() is called there is no way to add new cron jobs, neither to remove old one.
One way of making this possible is to read a DB (maybe flat DB - a simple text file) let's say every 1 minute and to update the list of the cron jobs according to DB's content.
There are 10 types of people in this world, those who understand binary and those who don't
User avatar
s.dot
Tranquility In Moderation
Posts: 5001
Joined: Sun Feb 06, 2005 7:18 pm
Location: Indiana

Post by s.dot »

Thanks for the suggestion, but I would rather keep this in one file.

I would like to implement a kill() method, so a user wouldn't have to restart apache to stop the script. But I don't know how to go about that.
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.
User avatar
onion2k
Jedi Mod
Posts: 5263
Joined: Tue Dec 21, 2004 5:03 pm
Location: usrlab.com

Post by onion2k »

scottayy wrote:I would like to implement a kill() method, so a user wouldn't have to restart apache to stop the script. But I don't know how to go about that.
The script would need to listen for something. You could have it create a socket and listen to that, but that's a lot of work. A simpler solution would be to check for the existence of a file. So your script would do something like..

Code: Select all

if (file_exists("kill.txt")) {
  unlink("kill.txt");
  exit;
}
To kill the script you'd just call a script that creates the kill.txt file.
User avatar
VladSun
DevNet Master
Posts: 4313
Joined: Wed Jun 27, 2007 9:44 am
Location: Sofia, Bulgaria

Post by VladSun »

Waht about a pure system call to kill?

Code: Select all

kill -s 9 `pgrep fakecron.php`
The only issue here is that is not going to work under Windows OS - but that not my concern ;)
There are 10 types of people in this world, those who understand binary and those who don't
User avatar
s.dot
Tranquility In Moderation
Posts: 5001
Joined: Sun Feb 06, 2005 7:18 pm
Location: Indiana

Post by s.dot »

Okay, I edited the script.

Took up Onion2k's suggestion to check for kill.txt, which can be manually created or a script can be created to kill the script. Fake Cron will then attempt to delete the file, then exit, so Fake Cron can be ran again.

Also, I added the ability to pass an array of times to the addCron method to run a script at multiple times each day.

There is one problem I see. If you tell it to run a script at 1 PM, it will run successfully for the first day, but every day after that the timestamp will be old (because the script is still running). I need a proposal on how to update the timestamp if the script is to be ran every day.
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.
User avatar
VladSun
DevNet Master
Posts: 4313
Joined: Wed Jun 27, 2007 9:44 am
Location: Sofia, Bulgaria

Post by VladSun »

1. There should be some check before executing the script - if the script is already runing ...
2. crontabs has already every functionality one can ask for - just follow its model...
There are 10 types of people in this world, those who understand binary and those who don't
User avatar
s.dot
Tranquility In Moderation
Posts: 5001
Joined: Sun Feb 06, 2005 7:18 pm
Location: Indiana

Post by s.dot »

VladSun wrote:1. There should be some check before executing the script - if the script is already runing ...
Thought about that. I need to think of a way to do this.
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Generate another file like a .pid.
User avatar
VladSun
DevNet Master
Posts: 4313
Joined: Wed Jun 27, 2007 9:44 am
Location: Sofia, Bulgaria

Post by VladSun »

Code: Select all

if (system('pgrep fakecron.php') === '')
{
    // allow runing the script
}
Beware of lock-file aproach - if for some reason it is not deleted (i.e. abnormal exit of fakecron.php) you will not be able to run this script and you will have to manually delete the lock-file.
There are 10 types of people in this world, those who understand binary and those who don't
User avatar
VladSun
DevNet Master
Posts: 4313
Joined: Wed Jun 27, 2007 9:44 am
Location: Sofia, Bulgaria

Post by VladSun »

feyd wrote:Generate another file like a .pid.
That is exactly what you must beware of ;)
There are 10 types of people in this world, those who understand binary and those who don't
User avatar
s.dot
Tranquility In Moderation
Posts: 5001
Joined: Sun Feb 06, 2005 7:18 pm
Location: Indiana

Post by s.dot »

Actually I believe if you lock a file, the file will remain locked until the script is finished executing or no longer running. So if I create a .pid file, and lock it. I can check if i can read/write to the .pid file, and this will tell me if the script is already running.

As far as I know, file locks are automatically unlocked by the operating system, right?
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.
Post Reply