Home » Laravel » Task Scheduling in Laravel

Task Scheduling in Laravel

Laravel framework supports console commands based on Symfony commands. You can create a command, add some functionality to it and run it in a command line. These commands can also be scheduled for regular execution using the Laravel scheduler.

In this article we will explain how to do task scheduling in Laravel. We will create a command, schedule it and configure the Laravel scheduler to get it working.

How to Schedule Tasks in Laravel

I assume that you have installed PHP and deployed the Laravel project. If you haven’t, see this article first.

1. Create Command

Let’s create a TimeLogCommand for this example. This command will save the current date and time to a file. To create the command you can use Artisan:

php artisan make:command TimeLogCommand

After this the command will appear in the app/Console/Commands directory. First of all, change the command signature. When you want to run this command use the command identifier from the $signature variable. For example, we can use time:log:

public $signature = "time:log";

Then add functionality to the handle() method. You can use Storage facade to work with the file system and Carbon to get current date:

public function handle() { $line = Carbon::now()->format("m/d/Y H:i:s\n"); $this->info("Current time: " . $line); Storage::append("time.log", $line); return self::SUCCESS; }

Here’s a full code of this class:

<?php namespace App\Console\Commands; use Carbon\Carbon; use Illuminate\Console\Command; use Illuminate\Support\Facades\Storage; class TimeLogCommand extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = "time:log"; /** * The console command description. * * @var string */ protected $description = "Command description"; /** * Execute the console command. * * @return int */ public function handle() { $line = Carbon::now()->format("m/d/Y H:i:s\n"); $this->info("Current time: " . $line); Storage::append("time.log", $line); return self::SUCCESS; } }

You can list recently added commands using Artisan:

php artisan list

As I said above, you can run the command using its identifier from signature. For example:

php artisan time:log

Then find the time.log file in the storage/app directory and look through its content. You will find the current date and time there.

2. Schedule Tasks

If you want this command to be executed regularly, use task scheduling in Laravel. The framework has a built in scheduler. It is quite simple to schedule tasks and run Laravel job from time to time here. Open the app/Console/Kernel.php file and find the schedule() method. Call command method from the object of Schedule class and pass your command class name as the first parameter. After this use one of the methods determining cron expression. For example, here’s a Laravel schedule for every minute:


You can use raw cron expression or one of the helpers. You can found a some of helpers in the table below:

->cron()Use raw cron expression.
->everyTwoMinutes()Run the task every minute.
->everyThreeMinutes()Run the task every three minutes.
->everyFourMinutes()Run the task every four minutes.
->everyFiveHMinutes()Run the task every five minutes.
->everyTenMinutes()Run the task every ten minutes.
->everyFifteenMinutes()Run the task every fifteen minutes.
->hourly()Run the task every hour.
->hourlyAt()Run the task every hour at a specified time.
->everyTwoHours()Run the task every two hours.
->everyThreeHours()Run the task every three hours.
->everyFourHours()Run the task every four hours.
->everySixHours()Run the task every six hours.
->daily()Run the task every day.
Run the task every day at a specified time.
->twiceDaily()Run the task twice per day.
->weekdays()Run the task only on weekdays.
->weekends()Run the task only on weekends.
->weekly()Run the task every week.
->weeklyOn()Run the task every week, on a specified day.
->mondays()Run the task every Monday.
->tuesdays()Run the task every Tuesday.
->wednesdayes()Run the task every Wednesday.
->thursdays()Run the task every Thursday.
->fridays()Run the task every Friday.
->saturdays()Run the task every Saturday.
->sundays()Run the task every Sunday.
->monthly()Run the task every month.
->monthlyOn()Run the task every month on a specified day.
->twiceMonthly()Run the task twice month.
->lastDayOfMonth()Run the task on the last day of the month.
->quarterly()Run the task every quarter.
->yearly()Run the task every year.
->yearlyOn()Run the task every year on a specified day.

These methods modify the current cron expression for a command. So you can use two or more of them in a chain. For example:

$schedule ->command(TimeLogCommand::class) ->mondays() ->everyMinute();

3. Configure Overlapping

If execution of your command takes a lot of time, the scheduler might run another copy of this command. If you don’t want it, use the method withoutOverlapping(). You can set in the first argument how many minutes must pass before the lock expires. For example:

$schedule ->command(TimeLogCommand::class) ->everyMinute() ->withoutOverlapping(10);

In this example, the command will run every minute if it is not already running or if the previous command runs longer than 10 minutes. You should be careful with withoutOverlapping method. It will create a lock mutex and if your command fall down, this mutex will still exists. So your command will never run after that. You can limit overlapping time to avoid it. If this has already happened, you can clear the cache. By default Laravel uses configured cache to store schedule mutex. Use the command below to do this:

php artisan cache:clear

4. Command Output

You can save the output of the scheduled command to a file. It will be helpful if you want to check the history of what the command outputs. There are a few methods to save the output. You can find them all in the table below:

->appendOutputTo()Append command output to a file.
->emailOutputTo()Send command output to Email.
->storeOutput()Save command output to a file with a random name in the storage/logs directory
->sendOutputTo()Save output to a given file.
->onFailureWithOutput()Set a closure function that will run when the command fails.
->onSuccessWithOutput()Set a closure function that will run when command succeeds.
->thenWithOutput()Set a closure function that will run when command execution finishes.

For example, you can save output in a random file:

$schedule ->command(TimeLogCommand::class) ->everyMinute() ->storeOutput();

After this you will find the schedule-*.log in the storage/logs directory:

Note that to use onFailureWithOutput(), onSuccessWithOutput(), thenWithOutput(), the output has to be saved to a file. If you do not use any of these functions storeOutput() is used by default.

5. Configure scheduler

There are two ways to configure the scheduler. In any case you need an external service to get it working. You can add Artisan command schedule:run to system cron and make it run every minute. Or you can and schedule:work command to supervisor or run it manually.

The first command will try to run scheduled tasks that should run at the current time. It uses dragonmantank/cron-expression package to determine if the task should run. At the moment of writing, it uses code below:

return $this->getNextRunDate($currentTime, 0, true)->getTimestamp() === $currentTime->getTimestamp();

So, it is trying to get the next run date with time in seconds and compare it with the current time in seconds. It means that if you want to run a command every minute, you should execute schedule:run command at zero seconds every minute. If you execute it later – the command won’t work.

You can add schedule:run command to system cron, but consider that Linux cron runs tasks one by one putting them in a queue. If it doesn’t run the command at zero seconds – the command won’t work. Here’s an example of how to set crontab with the Laravel schedule to run if you want to use it this way:

crontab -e * * * * * cd /path/to/project && php artisan schedule:run >> /dev/null 2>&1

But if it doesn’t work, there is a simple answer to how to run the scheduler in Laravel. You can use the supervisor process manager and Artisan command schedule:work. This command runs in the background and calls a schedule:run command when required. You can run it manually for development purposes:

php artisan schedule:work

Or you can add a section like this to your supervisor configuration file:

[program:publisher-schedule-worker-run] process_name=%(program_name)s_%(process_num)02d command= php artisan schedule:work directory = /path/to/project autostart=true autorestart=true numprocs=1 user=www-data

Pay attention, that in any case Artisan commands should run from user who owes PHP files of your project. In this example, we use the www-data user.

5. Scheduled Tasks Monitoring

It would be great to have monitoring for scheduled tasks and know when your tasks fail or see the last successful run. You can use a package from Spatie to do this. The package is called spatie/laravel-schedule-monitor. You can find more about it on the official GitHub page.

To install the package run the command below:

composer require spatie/laravel-schedule-monitor

Then, publish and run migrations:

php artisan vendor:publish --provider="Spatie\ScheduleMonitor\ScheduleMonitorServiceProvider" --tag="schedule-monitor-migrations" php artisan migrate

After that, sync scheduled tasks with the database:

php artisan schedule-monitor:sync

Then you can look at statistics using the following command:

php artisan schedule:monitor:list

Wrapping Up

In this article I have explained how to work with task scheduling in Laravel. It has a few underlying potential issues, but now you know why they are happening and how to avoid them. If you have any questions, use the comment form below.

Your Reaction

3 thoughts on “Task Scheduling in Laravel”

  1. Hi, Neat рost. There’s an issue together with your
    website in internet explorer, could test thіs?
    IE nonetheless is the market leader and a big component of other folks will leave
    out your fɑntastic writing due to this problem.


Leave a Comment