I have a Laravel 5.5 installation and am trying to get the scheduler to run. I have the following cron job running and it is working fine.
* * * * * php /var/www/html/project1/artisan schedule:run >> /var/www/html/project1/schedule.log
The cron job is outputting to a log file and I get the same result in cron as I get if I run artisan schedule:run from the command line. The result is always the same and says no scheduled commands are ready to run. The problem doesn't appear to be with cron as the job runs and I get output.
I configured the simple artisan inspire command to run in the Laravel schedule function. I can run the inspire command on the command line with php artisan inspire and it works fine. I understand all the posts about timezone but it is not a timezone issue, the command simply doesn't run ever. I am also not using withoutOverlapping(), so that is not my problem. So I have a cron job running every minute to run the laravel schedule and it does output to my log, which indicates that cron and Laravel are communicating. I think the problem must be that Laravel doesn't think there is a command that needs to be executed. I don't know how to debug this any further so any help would be greatly appreciated.
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
protected $commands = [
//
];
protected function schedule(Schedule $schedule)
{
$schedule->command('inspire')
->everyMinute();
}
protected function commands()
{
require base_path('routes/console.php');
}
}
Related
I run the php artisan: schedule run command and it shows the messages saying that the commands are running. However, nothing happens (the events the commands trigger), it did not work, what can it be?
Kernel.php
<?php
namespace App\Console;
use App\Console\Commands\CheckPayments;
use App\Console\Commands\CheckSubscriptions;
use App\Console\Commands\DeleteOperationalLogs;
use App\Console\Commands\GenerateInvoices;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
protected $commands = [
CheckPayments::class,
GenerateInvoices::class,
CheckSubscriptions::class,
DeleteOperationalLogs::class
];
protected function schedule(Schedule $schedule)
{
$schedule->command(CheckPayments::class, ['--force'])->everyMinute();
$schedule->command(GenerateInvoices::class, ['--force'])->everyMinute();
$schedule->command(CheckSubscriptions::class, ['--force'])->everyMinute();
$schedule->command(DeleteOperationalLogs::class, ['--force'])->everyMinute();
}
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
After run php artisan schedule:
Running scheduled command: "C:\xampp\php\php.exe" "artisan" payments:check --force > "NUL" 2>&1
Running scheduled command: "C:\xampp\php\php.exe" "artisan" subscriptions:check --force > "NUL" 2>&1
Running scheduled command: "C:\xampp\php\php.exe" "artisan" invoices:generate --force > "NUL" 2>&1
Running scheduled command: "C:\xampp\php\php.exe" "artisan" logs:delete --force > "NUL" 2>&1
Note: if I run the commands separately it works, for example: php artisan payments: check
To use a Command in your scheduler, you can use it's signature, or it's Classname. Each Command in App\Console\Commands has the following:
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = "example:command";
Once the Command is imported into App\Console\Kernel.php, in the protected $commands = []; array, it can be used in the schedule() function, but using ExampleCommand::class isn't correct:
protected function schedule(Schedule $schedule){
$schedule->command("example:command --force")->everyMinute();
$schedule->command(ExampleCommand::class, ["--force"])->everyMinute();
...
}
The main issue here seems to be with the --force option throwing the following error:
"--force" option does not exist
Many of the existing Laravel commands have the --force flag set, which, from the documentation does the following:
Force the operation to run when in production.
Many artisan commands prompt for input when you run a command, like php artisan migrate, that asks
Are you sure you want to run this command in production?
Since the scheduler is non-interactive, the --force flag will override this prompt to "Yes". That all being said, you need to define and handle the option yourself:
protected $signature = "example:command {--force}";
public function handle(){
$force = $this->option("force");
if(env("APP_ENV", "production") == "production" && !$force){
if(!$this->ask("Are you sure you want to run this in production?")){
return false; // or dd();, etc.
}
}
}
This is untested, but if APP_ENV=production is set in .env, and $force is null (default if --force isn't included), then it will prompt for confirmation, and exit if "No" is answered.
Try this
php artisan schedule:work
I have deployed laravel 5.4 app in AWS Ubuntu 16.04 apache2, i have created task scheduler for sending emails dailyAt('10:00').
When i run the artisan command php artisan email:reminder manually every thing works fine.
But when i run php artisan schedule:run i am getting No scheduled commands are ready to run.
I have also ran * * * * * php /var/www/html/app/artisan schedule:run >> /dev/null 2>&1 referring to documentation.
This is Kernal.php
class Kernel extends ConsoleKernel
{
protected $commands = [
\App\Console\Commands\EmailReminder::class,
];
protected function schedule(Schedule $schedule)
{
$schedule->command('email:reminder --force')->dailyAt('10:00');
}
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
Your schedule will only work if you call it at 10:00,
add this cronjob
* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
Laravel will call this function everyminute, and once it is 10:00 it will call the function accordingly.
Check https://laravel.com/docs/5.5/scheduling#introduction , search for 'Starting The Scheduler'
In AWS ECS we can use this without adding cron in to the container
https://github.com/spatie/laravel-cronless-schedule
php artisan schedule:run-cronless
According to the following tutorial (https://laravel.com/docs/5.5/scheduling) I came up with the following script to schedule Jobs within my Lumen application:
namespace App\Console;
use App\Jobs\ClearAccessLog;
use Illuminate\Console\Scheduling\Schedule;
use Laravel\Lumen\Console\Kernel as ConsoleKernel;
use App\Jobs\Special\DeleteCache;
use App\Jobs\Special\FetchRemoteArticles;
use App\Jobs\Special\FetchUpdateCategories;
use App\Jobs\Special\UpdateArticles;
use Illuminate\Support\Facades\Queue;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* #var array
*/
protected $commands = [
//
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->call(function() {
Queue::bulk([
new FetchUpdateCategories,
new FetchRemoteArticles,
new UpdateArticles,
new DeleteCache
],null,'specialqueue');
})->daily();
// listen to
$schedule->job(new ClearAccessLog())->weekly();
// listen to the helpdocs queue
$schedule->command('php artisan queue:work --timeout=0 --memory=4096 --queue=specialqueue')->everyFiveMinutes();
// listen to default jobs
$schedule->command('php artisan queue:work --timeout=0 --memory=4096')->daily();
}
}
According to the docs with my server I only have to register one single cronjob like this:
crontab -e
Then add:
* * * * * php /path-to-my-project/artisan schedule:run >> /dev/null 2>&1
Anyway I noticed that if I execute
php artisan queue:work --timeout=0 --memory=4096 --queue=specialqueue
via SSH this keeps listening until the command is stopped, therefore I am not sure if the Scheduler will start a new background task every five minutes while the others are still running?
How may I start this command only once? In general do you see some obvious mistake (I am new to this topic)?
You are not correct to start queue workers on schedule. Queue workers are daemon that listens if any job to work, if not, then it will sleep until next jobs are available. What you are trying to do is to create infinite queue workers that do not make sense.
You should check the manual Laravel Queues. If you are allowed to install Supervisor, let the supervisor controls your queue worker. Supervisor helps you to monitor queue workers and in any case it fails with some error, it will try to restart.
Or otherwise, you should start the queue worker in background through ssh, and detach the process from the current user. But the queue worker will not restart automatically in case of any failure.
I have a command scheduled in the Laravel 5.4 scheduler and would like to start the Laravel cron on Mac OS X El Capitan.
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\GetToken'
];
protected function schedule(Schedule $schedule) {
$schedule->command('gettoken')->everyMinute();
}
protected function commands() {
require base_path('routes/console.php');
}
}
My GetToken.php makes an API call and then a DB change. I believe that this is working properly, as I can run the task directly from the cli using:
php /path/to/project/artisan schedule:run 1>> /dev/null 2>&1
To edit my cron file I use:
env EDITOR=nano crontab -e
I then add:
* * * * * php /path/to/project/artisan schedule:run >> /dev/null 2>&1
I save with ctrl+o and exit with ctrl+x.
Re-editing the file shows that the changes have saved.
Running crontab -l shows the text that I entered into the crontab file.
My cron never runs. I can only get it to run once by running manually using the command I mentioned above.
Not directly answering your question, but proposing another solution:
If you want to set up cron jobs for your development environment, it's best to use Homestead, for its Linux standards compliance.
For small projects that i develop directly inside macOS, i run the following command inside the project root (in a separate terminal tab) to have my jobs run every minute:
while true; do php artisan schedule:run; sleep 60; done
This helps to make sure, the cron jobs are only run while i'm developing. When i'm done, i Ctrl+C that command and can be sure nothing unexpected happens while i'm not watching.
Plus it gives me the freedom to adjust the interval, by simple choosing another number of seconds for the sleep command. This can save time when developing.
Update Laravel 8.x
Laravel now offers the above as a single artisan command:
php artisan schedule:work
My laravel version is 5.0.28, I build on cloud9, and I added this command to my cron:
#!/bin/bash
PATH=/usr/bin
* * * * * php /home/ubuntu/workspace/app/artisan scheduled:run 1>> /dev/null 2>&1
I added this code on my Kernel.php. I referenced this site: https://laravel-news.com/2014/11/laravel-5-scheduler/
<?php namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use App\Http\Controllers\ApiController;
class Kernel extends ConsoleKernel {
protected $commands = [
'App\Console\Commands\Inspire',
];
protected function schedule(Schedule $schedule)
{
$schedule->call('ApiController#test_job')->hourly();
}
}
I waited and it still didn't work, so I tried to use the command php artisan schedule:run, and I got: No scheduled commands are ready to run.
I searched and found this answer: Laravel 5 "Class does not exist" when using the scheduler
So I modified my code. Also, this code had no specified time, so I modified my cron to specify a time, but it still doesn't work. I have no more ideas. please help. Thanks.
code
$schedule->call(join('#', [ApiController::class, 'test_job']));
cron
0 0,3,6,9,12,15,18,21 * * * php /home/ubuntu/workspace/app/artisan schedule:run 1>> /dev/null 2>&1
30 1,4,7,10,13,16,19,22 * * * php /home/ubuntu/workspace/app/artisan schedule:run 1>> /dev/null 2>&1
first to Test if cron is running in your server or localhost type:
> sudo service cron status
if not installed:
> sudo apt-get install cron
to enable laravel's scheduler:
> crontab -e
and you can select an editor if not vim opens directly. Be sure to enter there this line at the bottom:
* * * * * php /path_from_root_to_laravel_proj_folder/artisan schedule:run 1>> /dev/null 2>&1
to Test if you have setup inside laravel the scheduler right, run this from your projects folder:
>php artisan schedule:run
this should execute the tasks and tell you what is doing.
Laravel scheduler works with commands, not with controller methods:
create command:
php artisan make:command PurchasePodcast
edit command:
namespace App\Console\Commands;
use Illuminate\Console\Command;
class PurchasePodcast extends Command
{
protected $name = 'purchase:podcast';
public function fire()
{
// do stuff here
}
}
add command to Console\Kernel.php:
protected $commands = [
'App\Console\Commands\PurchasePodcast',
];
use command in scheduler:
$schedule->command('purchase:podcast')->hourly();
In my case, the scheduler actually run but encountered an error because of lower php version, beside artisan path (which is your project folder), I had to set the php path as below:
* * * * * /path_to_php_folder/bin/php /path_from_root_to_laravel_proj_folder/artisan schedule:run 1>> /dev/null 2>&1
There are several aspects to find the cause:
First, check whether the 'timezone' in config/app.php is set properly. Laravel will reset the timezone even though you already configured it in php.ini.
Secondly, check that crontab is working as expected. When you get the message "No schedule to be ready", it means your crontab is running and can detect the php and artisan command.
In order to complete #limonte's answer the create Console Command is the following:
php artisan make:console CampaignsCollect --command=campaigns:collect
Reference here: link