Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 301
Sam Avatar asked Oct 11 '22 00:10

Sam


2 Answers

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;
}
like image 130
muz the axe Avatar answered Oct 18 '22 09:10

muz the axe


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.

like image 25
chelmertz Avatar answered Oct 18 '22 07:10

chelmertz