Laravel schedule not respecting time - laravel

I am using Laravel 9 and I am trying to set several tasks in my schedule.
One of them should be called every minutes the other every 5 minutes .
protected function schedule(Schedule $schedule)
{
$schedule->call(/* send myself a mail */)->everyMinute();
$schedule->call(/* send myself a mail */)->everyFiveMinutes();
}
On my host I have a cron task called every minutes :
/opt/alt/php81/usr/bin/php ~/my-path/artisan schedule:run
However every minutes I receive the mail from my everyMinute() task, and the mail from my everyFiveMinutes() task.
I tried with job and command instead of call but it doesn't changes anything, same with ->cron('* * * * *') instead of ->everyMinute()

I had the very same issue.
I discover that when I use the schedule like this:
$schedule->call( MyController::MyFunction() )->everyFiveMinutes();
It run every minute, not every 5 minute as it would suppose to run.
If I run like this, every works as expect:
$schedule->call(function () {MyController::MyFunction();})->everyFiveMinutes();

Related

I am trying to run a task schedule on cPanel but not working

I am trying to run cron job on the daily bases at 16:00 but unfortunately not working please help me thanks
Note :- when i select schedule ->everMinute() it works perfectly.
/home3/urbanhq6/public_html/new/app/Console/Kernel.php
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('reminder:email')
->dailyAt('16:00');
}
cron job timing set
Minute Hour Day Month Weekday
0 16 * * *
First, you should adjust your cPanel cron to run every minute, with timings of * * * * *. Laravel handles its own scheduling via rules (like ->dailyAt('16:00')) in the Kernel.php file; running every minute lets Laravel do that without needing adjustments when you add a new command to the schedule.
Now, running at 0 16 * * * should still work for this particular set of rules. The likely answer is your server and your Laravel are on different timezones - check the timezone on the server with date, and check config/app.php's timezone value.
If there's a mismatch, your cron is running at 16:00 server time, but Laravel is adjusting the time to its own timezone, which means the two don't match. Switching your cron to * * * * * will fix this - the cron will start running (as it does with everyMinute()) - but the task will run at an unexpected hour.

Laravel Scheduler and Cron - how does Laravel know not to run the scheduled jobs based on daily(), hourly() etc

In Laravel, in my Kernel, I have:
protected $commands = [
Commands\SendRenewEmails::class,
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')
// ->hourly();
$schedule->command('renew:emails')
->daily();
}
The said function renew:emails, works as intended if I run this manually trough Artisan.
And in my crontab I have:
* */8 * * * cd /path-to-my-project && php artisan schedule:run >> /dev/null 2>&1
I have this to run every 8th hour, instead of every minute at * * * * *, since this is live for testing, and just to ensure that the task wasnt run every minute.
So how does Laravel know, when to run the daily job on the kernal, and when does this happen?
From this setup (which seems to be the basic setup for cronjobs in Laravel, but to run every minute instead of every 8th hour), there is no logs (that I can see), and no table in DB to keep track of this.
So if I where to set my cron to * * * * *, how does Laravel know not to run the scheduled job every minute, just because I have put ->daily(); at the end of the job?
And when I have daily();, at what specific time is that? And at specific what time is hourly();?
TL;DR:
How does Laravel know not to run the same jobs again if it is not supposed to, for example with daily(); rule? Where is this information stored? How can I be certain that a job with rule daily(); wont run every minute if my cronjobs std:out's php artisan schedule:run every minute?
Under the hood, the Laravel Scheduler uses https://github.com/dragonmantank/cron-expression to determine if a command or job is scheduled to run at the given minute the schedule:run is called.
Each task you schedule translates to a cron expression, which is then passed into the package. A method called isDue is then run against that expression to determine whether or not it should run. So, if you set a task to run hourly, then isDue will yield true at the top of the hour, and Laravel will execute to the task within the cron cycle.
As such, the information does not need to be stored anywhere, as determination is done on the fly.
This might also lead you to wonder what might happen if you have a long-running task that might take longer than the interval. This is where withoutOverlapping comes into the picture. When called, it creates what is known as a mutex, which is similar to a 'lock' of sorts (see What is a mutex? for more information), when the task is initially run. If a mutex already exists for a particular task on subsquent cycles, it means that task is currently running in another cycle, and should not be triggered again in this one.
Where are mutexes stored? Simple: Laravel stores them in a cache, and when a mutexed task is finished, the mutex is removed from the cache. And so the cycle continues.
I could go into much further detail here, but I think this answers your question for the most part.

Run schedule every five minutes (like 00:05, 00:10...) in laravel

I want to run the schedule every five minutes.
like 12:00, 12:05, 12:10...n
I'm using the Schedule Frequency Options :
->everyFiveMinutes();
But sometime it will start 12:02, 12:07, 12:12...n It's wrong for me.
So how can I run schedule every five mins special mins like +5?
try this
$schedule->command('your:job')->cron('5 0 * * *');
The command in this like will be executed at the five minutes of every day (0h05 or 12h05am) and so on.
You have to express this in cron notation:
$schedule->command('my:command')->cron('0,5,10,15,20,25,30,35,40,45,50,55 * * * *');

can run a task every X second with Laravel?

Hy guys, I have read the chapter called scheduling of Laravel's documentation, but
I haven't found much information. I'm trying to customize the execution of a task to make it run every 30 seconds. Is there a solution ?
Sorry for my english and have a good day.
By default CRON tasks are scheduled in minimal period 1 minute, but there is workaround for your issue.
In Console Kernel you should do something like this:
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('your_command:run', ['--delay'=> 0])->everyMinute();
$schedule->command('your_command:run', ['--delay'=> 30])->everyMinute();
}
In your Command class you should define the $signature variable that can take the delay parameter.
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'your_command:run {--delay= : Number of seconds to delay command}';
In the handle method you should read value of this parameter and sleep this task for specific number of second using built-in sleep() function.
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
// code
sleep(intval($this->option('delay')));
}
This solution will run your task every 30 seconds, you can multiply number of task with different delay. In this case you need to edit schedule method in Kernel class.
I've got this quote on the Laravel docs...
In the past, developers have generated a Cron entry for each task they need to schedule. However, this is a headache. Your task schedule is no longer in source control, and you must SSH into your server to add the Cron entries. The Laravel command scheduler allows you to fluently and expressively define your command schedule within Laravel itself, and only a single Cron entry is needed on your server.
You still need to use Cron to run your tasks but using the Laravel's Scheduling you set only one job on the Cron and control all the jobs of your application through the Task Scheduling.
Example:
Set this cron on your server:
* * * * * php /path/to/artisan schedule:run
It is gonna call the Laravel command scheduler every minute and then, Laravel evaluates your scheduled tasks and runs the tasks that are due.
Then on your file app/Console/Kernel.php you can configure all your tasks as the code below:
$schedule->call(function () {
DB::table('recent_users')->delete();
})->daily();
$schedule->command('inspire')->hourly();

Laravel liebig/cron executes the cronjob twice for same time

I am using laravel 4.2.
I've a project requirement to send some analysis report email to all the users every Monday 6 am.
Obviously its a scheduled task, hence I've decided to use cron-job.
For this I've installed liebig/cron package. The package is installed successfully. To test email, I've added following code in app/start/global.php:
Event::listen('cron.collectJobs', function() {
Cron::setEnablePreventOverlapping();
// to test the email, I am setting the day of week to today i.e. Tuesday
Cron::add('send analytical data', '* * * * 2', function() {
$maildata = array('email' => 'somedomain#some.com');
Mail::send('emails.analytics', $maildata, function($message){
$message->to('some_email#gmail.com', 'name of user')->subject('somedomain.com analytic report');
});
return null;
}, true);
Cron::run();
});
Also in app\config\packages\liebig\cron\config.php the key preventOverlapping is set to true.
Now, if I run it like php artisan cron:run, it sends the same email twice with the same time.
I've deployed the same code on my DigitalOcean development server (ubuntu) and set its crontab to execute this command every minute but still it is sending the same email twice.
Also it is not generating lock file in app/storage directory, according to some search results I've come to know that it creates a lock file to prevent overlapping. the directory has full permissions granted.
Can anybody knows how to solve it?
Remove Cron::run().
Here's what's happening:
Your Cron route or cron:run command is invoked.
Cron fires off the cron.collectjobs event to get a list of events.
You call Cron::run() and run all the events.
Cron calls Cron::run() and runs all the events.
In the cron.collectjobs event you should only be making a list of jobs using Cron::add().
The reason you're not seeing a lock file is either that preventOverlapping is set to false (it's true by default), or that the jobs are running so fast you don't see it being created and deleted. The lock file only exists for the time the jobs run, which may only be milliseconds.

Resources