Run PHP script automatically without user input at certain conditions?
October 27, 2010 11:11 AM   Subscribe

How do I make a PHP script run only once if certain conditions are met, without involving the users?

I'm writing an online e-game with PHP. I need to figure out how to run the "tick.php" script automatically once a certain condition— a certain amount of elapsed time since a MySQL field— is met. This script must only be run once, at that time, and not be dependent on any kind of user input. Currently, I have a button on the admin control panel that runs it, but obviously this will only run the script manually. The script has a lot of output which I would prefer to save somewhere for later access, although this is not completely necessary. I'm not a very good programmer so I assume there are lots of other things that I'm not considering. The script can take up to a minute to run.

Here some solutions I've considered and rejected:
1. Run the script on page load if the condition is met. Not a strong enough way to prevent the script from being run twice concurrently (i.e., if users load a page at the same time), no way to save the output (?), the page load will be delayed if the script is taking a while and if the user quits the page the script will be aborted, if no user is looking at pages at the time then the script won't run.

2. Cron job. Cron job can't check for the condition. I could run it more often than the condition and let the script run only if the condition is set, but this seems wasteful. I'm using Dreamhost for the project and I don't want to have a cron job running every minute.

3. Call the script as AJAX. Many of the same problems as #1.

4. Use PHP's internal tick functions. Not keyed to time, many of the same problems as #1.

5. Have dedicated team of game admins run ticks manually when the time is up. Haha, right.

Any suggestions are welcome. I know this is possible; I just don't know how to do it and Google seems to come up short.
posted by Electrius to Computers & Internet (10 answers total)
 
Cronjobs are the way to go, as everything else is unreliable. The way you describe the cronjob is quite right, but you need to store two additional fields: when it last ran the script (to be able to prevent it from executing twice) and possibly a "lock" field that is set to true at the start of the script and to false at the end, so the script can avoid running in parallel.

It might also be a good idea to see if you can rewrite the script itself to not have any side-effects in the case that it is run twice.

Apart from that - the cron job every minute will not be wasteful, as long as the core of the script gets only executed when necessary. A small script and a single database query per minute is completely negligible in terms of server load.
posted by uncle harold at 11:28 AM on October 27, 2010


Use the cron job.
posted by bitdamaged at 11:30 AM on October 27, 2010


I think a cron job would work fine. If your script runs before the right time, presumably all it needs to do is check the time and exit; that's a very cheap operation and it couldn't hurt you to run it every hour, minute, second, or whatever. I don't even see why you can't just have a script that runs continuously and not even bother with scheduling it at all.

If the timing needs to be very precise, and for some reason you're very concerned about running the script often, you could have an infrequently-running script that triggers another script to check the time much more often when the time is getting close. But to me that seems like overkill.
posted by Chicken Boolean at 11:48 AM on October 27, 2010


Why do you need the cron job to keep checking the time? Why not just (re-)schedule it for the right time in the first place?
posted by emilyw at 12:01 PM on October 27, 2010


uncle harold: "A small script and a single database query per minute is completely negligible in terms of server load."

Completely agree. If the "Is there work to be done?" query is worrying you from a performance standpoint, ur doin it wrong. Just make sure there's an index on that field.

Chicken Boolean: "I don't even see why you can't just have a script that runs continuously and not even bother with scheduling it at all."

I assume you mean running as some kind of daemon. Aside from the host provider probably not allowing that, you'd need to build in some kind of handling for when the daemon silently fails for whatever reason. For a simple task like this, a cron job that makes your process live and die each time is more straightforward.
posted by mkultra at 12:04 PM on October 27, 2010


I assume you mean running as some kind of daemon. Aside from the host provider probably not allowing that, you'd need to build in some kind of handling for when the daemon silently fails for whatever reason. For a simple task like this, a cron job that makes your process live and die each time is more straightforward.

Yes.
posted by Chicken Boolean at 12:12 PM on October 27, 2010


Nthing the cron job. That's not the only way to do it, but in the vast majority of the situations, it's the best.
posted by toomuchpete at 12:27 PM on October 27, 2010


I would also use cron with either a DB based lock or just flock on the executable itself (or maybe better, its logfile) to prevent multiple simultaneous executions. If you know when you need to run the script next within the script itself I would use at to schedule the next run.
posted by zengargoyle at 12:29 PM on October 27, 2010


Unless I'm missing something (and I may be because I'm not very familiar with Dreamhost), you should be able to write a tiny shell script (bash? not sure what shell Dreamhost uses) that checks the field in the mysql database (you'd probably need to read the output of the mysql command line call into a variable), compares it to the current time, then kicks off the "tick.php" script if necessary. This should definitely be lightweight enough to run every minute via a cronjob.

IMO, the more you can push this sort of operational/maintenance type thing down to the shell itself, the better -- it will be more stable than some higher-level mechanism you build, and it will be easier to troubleshoot.
posted by treepour at 3:42 PM on October 27, 2010


it will be more stable than some higher-level mechanism you build, and it will be easier to troubleshoot.

This is only going to be true if you are just as good at shell scripting as you are at the high-level language of your choice. If you know PHP, use PHP. The performance and stability gains of that kind of shell script over a similar PHP script are trivial at best, and if you're not great with shell scripting, there's a lot larger chance of coding error or edge case you're not familiar with.
posted by toomuchpete at 5:02 PM on October 27, 2010


« Older Th age of ebay innocence & The House of Mirth   |   how did this thing know how to fail post-warranty? Newer »
This thread is closed to new comments.