Introduction
The Laravel documentation covers all the information you need to configure Cron Jobs on your hosting machine. Some years ago we were required to define an entry on the server for each task we needed to schedule. Now with Laravel we can simply define a single entry that interacts with the Schedule object, which will take care to run the tasks that are due.
The only Cron entry needed on the server, is the following
* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1
Basically it means that every minute (* * * * *) php
will run the artisan
command schedule:run
. The notation >> /dev/null 2>&1
basically means that the standard output (STDOUT) is redirected to /dev/null
and so it is ignored, while 2>&1
means that STDERR is redirected to STDOUT1.
Define Jobs
In the schedule
method of the App\Console\Kernel
class you can define the tasks you are planning to execute, using a Closure
.
<?php
$schedule->call(function () {
// ... your code
})->daily();
The frequency of these tasks is defined by a variety of handy methods that Laravel provides, or you can simply use cron('* * * * *')
, if you are more familiar with the Cron notation.
Moreover the Schedule
class lets you schedule also Artisan commands
command('artisan:command')
or operating system commands
exec('')
The Problem
Frequently on cheap shared hostings you have not so much space for customization. In most of the cases these hosting providers doesn’t provide SSH access to their servers, instead they will only let you define tasks through the control panel. Sometimes you can’t even manually define a crontab entry, because the hosting allows you only to schedule URL calls. In these cases remember that you can always call Artisan commands via code, from a route or controller, using the Artisan
facade:
<?php
Route::get('/foo', function () {
$exitCode = Artisan::call('email:send', [
'user' => 1, '--queue' => 'default'
]);
});
Recently I stumbled upon a hosting provider which allows the use of manual crontab entries in the control panel, however every scheduled tasks configured in the Schedule
class was failing with a strange message:
'ErrorException' with message 'Invalid argument supplied for foreach()' in /home/project/vendor/symfony/console/Input/ArgvInput.php
My code was really straightforward
<?php
$schedule->command('newsletter:send')->daily();
After some googling turned out that the ini directive register_argc_argv
was disabled on the php.ini
and I needed to enable it explicitly on each call in order to accept argc
and argv
parameters. Luckily I easily solved this problem using exec
instead of command
<?php
$schedule->exec('php -d register_argc_argv=On /path/to/artisan newsletter:send')
Using exec however you don’t have access to emailOutputTo
and sendOutputTo
, which are exclusive to the command method.
Where not explicitly defined, STDIN, STDOUT and STDERR are numbered with 0, 1, and 2, in that order. ↩︎