Dispatcher allows you to schedule your artisan commands within your Laravel project, eliminating the need to touch the crontab when deploying. It also allows commands to run per environment and keeps your scheduling logic where it should be, in your version control.
use Indatus\Dispatcher\Scheduling\ScheduledCommand;
use Indatus\Dispatcher\Scheduling\Schedulable;
use Indatus\Dispatcher\Drivers\Cron\Scheduler;
class MyCommand extends ScheduledCommand {
//your command name, description etc.
public function schedule(Schedulable $scheduler)
{
//every day at 4:17am
return $scheduler
->daily()
->hours(4)
->minutes(17);
}
}
## Features
- Schedule artisan commands to run automatically
- Scheduling is maintained within your version control system
- Single source of truth for when and where commands run
- Schedule commands to run with arguments and options
- Run commands as other users
- Run commands in certain environments
By Ben Kuhl at the Laravel Louisville meetup (@lurvul): Video - Slides
By Jefferey Way at Laracasts: Recurring Tasks the Laravel Way
## InstallationRequires:
You can install the library via Composer by adding the following line to the require block of your composer.json file:
"indatus/dispatcher": "dev-master"
Next run composer update
.
Add this line to the providers array in your app/config/app.php
file :
'Indatus\Dispatcher\ServiceProvider',
To use with Cron, see the Cron driver section.
## Usagescheduled
scheduled:make Create a new scheduled artisan command
scheduled:run Run scheduled commands
scheduled:summary View a summary of all scheduled artisan commands
If commands are not visible via php artisan
then they cannot be scheduled.
Use php artisan scheduled:make
to generate a new scheduled command, the same way you would use artisan's command:make
. Then register your command with Laravel.
You may either implement \Indatus\Dispatcher\Scheduling\ScheduledCommandInterface
or follow the below steps.
- Extend
\Indatus\Dispatcher\Scheduling\ScheduledCommand
- Add use statements to your command. If you're using a custom driver you will use a different
Scheduler
class.
use Indatus\Dispatcher\Scheduling\ScheduledCommand;
use Indatus\Dispatcher\Scheduling\Schedulable;
use Indatus\Dispatcher\Drivers\Cron\Scheduler;
- Implement schedule():
/**
* When a command should run
*
* @param Scheduler $scheduler
* @return \Indatus\Dispatcher\Scheduling\Schedulable
*/
public function schedule(Schedulable $scheduler)
{
return $scheduler;
}
For details and examples on how to schedule, see Cron.
### Running Commands As UsersYou may override user()
to run a given artisan command as a specific user. Ensure your scheduled:run
artisan command is running as root.
public function user()
{
return 'backup';
}
### Environment-Specific CommandsThis feature may not be supported by all drivers.
You may override environment()
to ensure your command is only scheduled in specific environments. It should provide a single environment or an array of environments.
public function environment()
{
return ['development','staging'];
}
By default, cron commands will not run when application is in Maintenance Mode. This will prevent all sorts of weird output that might occur if a cron command is run while you are migrating a database or doing a composer update.
You may override runInMaintenanceMode()
to force your command to still be run while the application is in maintenance mode.
public function runInMaintenanceMode()
{
return true;
}
These examples utilize the cron driver.
You may schedule a given command to to run at multiple times by schedule()
returning multiple Schedulable
instances.
public function schedule(Schedulable $scheduler)
{
return [
// 5am Mon-Fri
$scheduler->everyWeekday()->hours(5),
// 2am every Saturday
App::make(get_class($scheduler))
->daysOfTheWeek(Scheduler::SATURDAY)
->hours(2)
];
}
You may also schedule a command to run with arguments and options.
public function schedule(Schedulable $scheduler)
{
return [
// equivalent to: php /path/to/artisan command:name /path/to/file
$scheduler->args(['/path/to/file'])
->everyWeekday()
->hours(5),
// equivalent to: php /path/to/artisan command:name /path/to/file --force --toDelete="expired" --exclude="admins" --exclude="developers"
$scheduler->args(['/path/to/file'])
->opts([
'force',
'toDelete' => 'expired',
'exclude' => [
'admins',
'developers'
]
])
->daysOfTheMonth([1, 15])
->hours(2)
];
}
## DriversBoth
args()
andopts()
, whichever is called first, will internally create a newSchedulable
instance for you so you don't need toApp::make()
.
While Cron is the default driver for Dispatcher, it can be used with any scheduling tool that can run artisan commands. See building custom drivers.
### Cron (Default)Add the following to your root Crontab (sudo crontab -e
):
* * * * * php /path/to/artisan scheduled:run 1>> /dev/null 2>&1
If you are adding this to /etc/cron.d
you'll need to specify a user immediately after * * * * *
.
If you'd like for scheduled commands to be able to run as different users, be sure to add this to the root Crontab. Otherwise all commands run as the user whose Crontab you've added this to.
Examples of how to schedule:
public function schedule(Schedulable $scheduler)
{
//every day at 4:17am
return $scheduler->daily()->hours(4)->minutes(17);
}
public function schedule(Schedulable $scheduler)
{
//every Tuesday/Thursday at 5:03am
return $scheduler->daysOfTheWeek([
Scheduler::TUESDAY,
Scheduler::THURSDAY
])->hours(5)->minutes(3);
}
You may also schedule commands via raw Cron expressions
public function schedule(Schedulable $scheduler)
{
//every other day at 3:15am, 4:15am and 5:15am
return $scheduler->setSchedule(15, [3,4,5], '*/2', '*', '*');
}
You can build your own drivers or extend a driver that's included. Create a packagepath such as \MyApp\ScheduleDriver\
and create two classes:
Scheduler
thatimplements Indatus\Dispatcher\Scheduling\Schedulable
. This class should provide a useful interface for programmers to schedule their commands.ScheduleService
thatextends \Indatus\Dispatcher\Services\ScheduleService
. This class contains logic on how to determine if a command is due to run.
Publish the configs using php artisan config:publish indatus/dispatcher
. Then update your driver configuration to reference the package in which these 2 classes are included (do not include a trailing slash):
'driver' => '\MyApp\ScheduleDriver'
I need to deploy to multiple servers representing a single environment. How can I be sure my command is only run by a single server and not run on each server?
Schedule scheduled:run
to run every minute with rcron:
* * * * * /usr/bin/rcron php /path/to/artisan scheduled:run 1>> /dev/null 2>&1
Why are my commands not running when I've scheduled them correctly? I'm also not seeing any error output
-
Verify that mcrypt is installed and working correctly via the command
php -i | mcrypt
. -
Utilizing
php artisan scheduled:run --debug
will tell you why they're not running. If you do not see your command listed here then it is not set up correctly.
Example:
$ php artisan scheduled:run --debug
Running commands...
backup:avatars: No schedules were due
command:name: No schedules were due
myTestCommand:name: No schedules were due
cache:clean: /usr/bin/env php /Users/myUser/myApp/artisan cache:clean > /dev/null &
mail:subscribers: /usr/bin/env php /Users/myUser/myApp/artisan mail:subscribers > /dev/null &
I have commands that extend ScheduledCommand
but why don't they appear in when I run scheduled:summary
?
Commands that are disabled will not appear here. Check and be sure isEnabled()
returns true on those commands.