Sam
Sam

Reputation: 4487

How should I create one-off scheduled tasks in PHP? Cron?

I'm creating a web app where users can specify a time and date to run 2 scheduled tasks (one at the start date and one at the end date). As these are only run once each I didn't know if a cron job would be appropriate.

The other option I thought of would be to save all of the task times to a DB and run a cron job every hour to check if $usertime == NOW(), etc. But I was worried about jobs overlapping, etc.

Thoughts?

Additional: Many users can create many tasks that run 2 scripts each.

Upvotes: 5

Views: 2618

Answers (3)

muz the axe
muz the axe

Reputation: 426

cron is great for scripts run on a regular basis, but if you want a one-off (or two-off) script to run at a particular time you would use the unix 'at' command, and you can do it directly from php using code like this:

/****
 * Schedule a command using the AT command
 *
 * To do this you need to ensure that the www-data user is allowed to
 * use the 'at' command - check this in /etc/at.deny
 *
 *
 * EXAMPLE USAGE ::
 *
 * scriptat( '/usr/bin/command-to-execute', 'time-to-run');
 * The time-to-run shoud be in this format: strftime("%Y%m%d%H%M", $unixtime)
 *
 **/

function scriptat( $cmd = null, $time = null ) {
    // Both parameters are required
    if (!$cmd) {
        error_log("******* ScriptAt: cmd not specified");
        return false;
    }
    if (!$time) {
        error_log("******* ScriptAt: time not specified");
        return false;
    }

    // We need to locate php (executable)
    if (!file_exists("/usr/bin/php")) {
        error_log("~ ScriptAt: Could not locate /usr/bin/php");
        return false;
    }

    $fullcmd = "/usr/bin/php -f $cmd";

    $r = popen("/usr/bin/at $time", "w");
    if (!$r) {
        error_log("~ ScriptAt: unable to open pipe for AT command");
        return false;
    }
    fwrite($r, $fullcmd);
    pclose($r);

    error_log("~ ScriptAt: cmd=${cmd} time=${time}");

    return true;
}

Upvotes: 2

Ed Heal
Ed Heal

Reputation: 59997

Whatever mechanism you chose (cron/at/daemon) I would only put the start task into the queue. Along with that start task is to place the end task. That part can either place it into the future or it the time has elapsed start it immediately. That way they will never overlap.

I would also favour the PHP/DB and cron option. Seems simpler and gives more flexibility - could chose multiple threads etc if performance dicttates.

Upvotes: 1

chelmertz
chelmertz

Reputation: 20601

I'd do it like that, save settings in a database and check when needed if the task should start.

You could run a checking/initiating cronjob every minute. Just make sure the checking code is not not too heavy (exits quickly). A database query for a couple of rows shouldn't be a problem to execute every minute.

If the "task" is really heavy, you should consider a daemon instead of a cronjob calling php. Here is a good & easy-to-read introduction: Create daemons in PHP


Edit: I took for granted that even if the tasks are only ran "once each", you have multiple users which are 1:1 to the "once each", thereby jobs for each user. If not, at (as the comments says) looks worthy of an experiment.

Upvotes: 1

Related Questions