Artisan Scheduler vs Cron

When running your application, there might be commands you wish to run at set intervals, such as performing backups, cleanup, sending emails and clearing cache. With Laravel 5.0, you now have two options - Cron, or Laravel's Command Scheduler.

Prior to Laravel 5.0, scheduling was done using dispatcher.

Cron

Scheduling

Cron is a program that execute commands or scripts at set intervals or times. More specifically, it is a daemon, which means it only needs to be started once and will continue to run in the background.

If you go to you machine and list the current processes, you will see an entry for crond

$ ps aux | grep crond
daniel   29860  0.0  0.0  15964   944 pts/15   S+   18:42   0:00 grep --color=auto crond

cron is the name of the service that runs the scheduled jobs, crond is the daemon that runs.

If you look inside the /etc/ directory, you'll find some files and directories starting with cron.

drwxr-xr-x   2 root root      4096 Mar 19 10:14 cron.d/
drwxr-xr-x   2 root root      4096 Apr 14 10:46 cron.daily/
drwxr-xr-x   2 root root      4096 Apr 17  2014 cron.hourly/
drwxr-xr-x   2 root root      4096 Apr 17  2014 cron.monthly/
-rw-r--r--   1 root root       722 Feb  9  2013 crontab
drwxr-xr-x   2 root root      4096 Feb 23 09:38 cron.weekly/

If you place a script inside one of the cron.***ly directories, it will be ran at that interval.

To specify your own intervals or time, add your commands to the /etc/crontab file.

The format of a valid entry goes like this:

minute hour dom month dow user cmd

So 01 * * * * root echo "Hello World" would print Hello World to the console the first minute of every hour. 01 * 26 12 * root echo "Boxing Day Cleanup" will be ran on the first minute of every hour on Boxing Day.

So, we can use Cron to set up jobs, including running artisan commands, by editing the /etc/crontab file.

Source Control

The /etc/crontab cannot be included in version control, because it's not in the project directory.

The workaround this is to include a cron directory within the application, it'll contain files equivalent to the /etc/crontab file. On each deployment, we can write a script to concatenate them to the /etc/crontab file on the machine.

This is indeed possible, but it's troublesome and non-standard, as different people can name their cron directory differently; then we'd have to change the /etc/crontab file again.

Command Scheduler

With the Command Scheduler, you can specify all the commands inside the schedule method of the Kernel class (defined inside app/Console/Kernel.php)

<?php namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel {
        protected $commands = [
                'App\Console\Commands\Inspire',
        ];
        protected function schedule(Schedule $schedule)
        {
                $schedule
                    ->command('inspire')
                    ->hourly();
        }

}

You can run the artisan schedule:run command to run the scheduler. Each time it is ran, artisan will check app/Console/Kernel.php to see if any scheduled jobs needs to be executed, and if so, executes them.

Thus, we only have to include one entry inside your /etc/crontab.

* * * * * php /path/to/artisan schedule:run 1>> /dev/null 2>&1

And the same entry can be set across your development, staging and production servers, even if different commands needs to be run later (see below).

So, we have all the scheduled jobs in one file, that is standardized and can be revision controlled, without running external scripts. That's a win.

Other benefits

The scheduler provides you with more readable methods such as hourly() or everyFiveMinutes(), but also gives you the power and flexibility of cron via the cron() method. Here you can define your own custom schedule using the same syntax.

$schedule->command('foo')->cron('* * * * *');

The scheduler also provides methods that'll allow you to, for example, run certain commands only in certain environments or states. Without the scheduler, you'd have to manually configure this yourself.

$schedule->command('foo')->monthly()->environments('production');

$schedule->command('foo')->monthly()->evenInMaintenanceMode();

Conclusion

Before Laravel 5, setting up a scheduled task involves Cron. The artisan scheduler makes doing this easier, more standardized.

comments powered by Disqus