In my Laravel scheduler I have many lines like the following
$schedule->command('commandname01')->everyMinute();
$schedule->command('commandname02')->everyMinute();
$schedule->command('commandname03')->everyMinute();
I have noticed that some command e.g. commandname02 is not running anymore
but commandname01 and commandname03 are running.
How could I restore the full commands execution?
Note: if i log into my container and run
php artisan commandname02
It will work fine.
Suspects:
Is it possible that Laravel scheduler stops executing one of the commands if it goes repeatedly on error?
Is it possible that, if commandname01 takes too long, commandname02 will be skipped at same minute execution?
Any other idea?
"Is it possible that, if commandname01 takes too long, commandname02 will be skipped at same minute execution?"
Yes and the reason is that command are not executed in parallel (multithread is not natively available in PHP) but sequentially within scheduler
So if commandname01 takes more than 60" for exec. commandname02 execution will be skipped in the same minute.
Resource: Laravel : Task Scheduling [ In Parallel ]
Solution I adopted and recommend, as provided in link above, it's to implement parallel task leveraging on crontab.
Launch batches to be run in parallel like:
* * * * * php /var/www/artisan batch01 >> /var/log/laravel-scheduler.log
* * * * * php /var/www/artisan batch02 >> /var/log/laravel-scheduler.log
And in batchNN commands just call your commands that can be run sequentially
Related
I have a dummy Command job set up, whose handle() function is as follows:
public function handle()
{
$this->line('==================');
$this->line('Running my job at ' . Carbon::now());
$this->line('Ending my job at ' . Carbon::now());
}
As you see, it doesn't actually do anything but return a few lines of info to the standard output.
Now, in my App\Console\Kernel class, I have set up the following schedule:
protected function schedule(Schedule $schedule)
{
$schedule
-> command('cbh:dummyCommand')
-> everyMinute()
-> appendOutputTo (storage_path().'/logs/laravel_output.log');
}
Now, from the command-line I run php artisan schedule:run. The output in my laravel_output.log file reads
==================
Running my job at 2018-02-08 11:01:33
Ending my job at 2018-02-08 11:01:33
So far so good. It seems that my schedule is running. However, if I run the command again within the same minute, my logfile now reads:
==================
Running my job at 2018-02-08 11:01:33
Ending my job at 2018-02-08 11:01:33
==================
Running my job at 2018-02-08 11:01:51
Ending my job at 2018-02-08 11:01:51
In other words, the schedule appears to be running more frequently than every minute, which appears to me to break the rules I defined in my schedule.
What's more confusing is that I can change the schedule to run every 5 minutes instead of every minute:
protected function schedule(Schedule $schedule)
{
$schedule
-> command('cbh:dummyCommand')
-> everyFiveMinutes()
-> appendOutputTo (storage_path().'/logs/laravel_output.log');
}
then run php artisan schedule:run, then I get the following output
No scheduled commands are ready to run.
I can wait as long as you like (i.e. more than 5 minutes) and still I get no output to my log file.
I observe exactly the same behaviour when I schedule my command with Windows Task Scheduler (yes, my development environment is a Windows 7 box, and yes, this is the Windows equivalent of a cron-job).
The Question
So what's going on? How does the artisan schedule:run command figure out which commands are "waiting" on the schedule to be executed? I had imagined that there would be some kind of log-file to record the fact that "Command X is on a 1-hour schedule and last ran at 09:00, so don't execute it again before 10:00", but I have been able to find no trace of such a log.
Can someone give me a clue?
Thanks!!
Not cool to answer your own question, I know. Anyhow, let's imagine this is my schedule:
protected function schedule(Schedule $schedule)
{
$schedule
-> command('cbh:dummyCommand')
-> everyFiveMinutes()
-> appendOutputTo ('/my/logs/laravel_output.log');
}
What I've discovered is that this code doesn't set your job to run every 5 minutes. Nor does it prevent the command running again if it was run less than 5-minutes ago.
A better way to think about it is that this code sets the named command "to be runnable every time the minute-figure of the current time is 0 or 5". In other words, if I run the command-line argument: php artisan schedule:run at 11:04, then the response is:
# No scheduled commands are ready to run.
But if I run the same command at 11:00 or 11:05, then we get:
# Running scheduled command: php artisan cbh:dummyCommand >> /my/logs/laravel_output.log 2>&1
And I end up with output in my log-file.
I discovered the above when my everyFiveMinutes() schedule was creating a log in my file every 10 minutes based on the fact that my task-scheduler was running every 2 minutes.
I'm answering this just to let other people know it (since I was having the same confusion).
Laravel scheduler does exactly the same job than Linux cron, by checking if a task cronned time (in minutes) is exactly the same of current time.
When you set in crontab * * * * * ... php artisan schedule:run >> ... you are running schedule:run every minute at 0 secs, like '1:00:00', '1:01:00', '1:02:00', etc.
So, if you set your command to run (let's say) on 'mondays at 1:00' in your Laravel scheduler, and you are on a monday at 1:00, it will be executed, regardless the current seconds. And the last part (seconds) is important to understand how it works.
For example, you are on monday at 1:00:05 (5 seconds after 1:00), so cron already launched schedule:run and your task is being executed. Then you open your terminal, go to your project's root directory and launch, manually, php artisan schedule:run. At that time, it may be 1:00:30 (30 seconds after 1:00). Well, now your task will be executed again because 1:00:30 is still part of 1:00. So you can execute N times schedule:run at 1:00 and it will execute N times your task scheduled to run at 1:00.
And that's the magic of no needing a table or a file to control process launching time. Minutes is the minimum unit in cron, so unless you are doing the things wrong (like duplicating schedule:run line, a hack to run a command more often than a minute, etc.) your Laravel tasks will be executing once at the desired time.
Just a note: Check that your timezone is correct in config/app.php. I got crazy to understand why things like everyMinute(), everyFiveMinutes() were working, and dailyAt('1:10') were not. Of course, with Laravel in UTC and me being in GMT-3 (server clock), I had a great difference in hours.
I have the following cron tasks:
/etc/cron.d/mongo
/etc/cron.d/elastic
These cron jobs only executes scripts located here:
/etc/script/mongo
/etc/script/elastic
These tasks execute every 30 minuts, that's the following cron format:
0,30 * * * *
I don't know why but these tasks aren't executing all times. In 2 hours, for example, they only execute 2-3 times and not 4. These tasks are performing backups, I need to be sure that they execute every 30 minuts.
Why this is happening?
PD: If i execute crontab -e the file is empty, this may cause any problem?
I am using Laravel Task Scheduling. I defined a custom command and set it to run every minute like:
$schedule->command('dailyk')->everyMinute();
Then I used the following command to run the task:
php /var/www/stockhit/artisan schedule:run 1>> /dev/null 2>&1
I used log to check that my custom command continued to run. However, it is not run every minute. Instead, it just ran once.
How can I make it run every minute, instead of just one time?
See Task Scheduling:
Here is the only Cron entry you need to add to your server:
* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1
This Cron will call the Laravel command scheduler every minute. Then, Laravel evaluates your scheduled tasks and runs the tasks that are due.
Laravel's task scheduler does not stay in memory, it needs to be run every minute. It will then check which tasks need to be run in that minute and run them.
When you run the task scheduler using PHP it just runs once, it needs cron to run it every minute.
you need to add a cron job. On ubuntu use the command
crontab -e
to open your cron job file, then add
* * * * * php /var/www/stockhit/artisan schedule:run 1>> /dev/null 2>&1
So, as far as I understand, commands are now jobs in Laravel 5.1. If I'd like to schedule a job, should I call a job from a command then (since the scheduler can only call commands and not jobs)?
In the dummy setup of Laravel 5.1 there still is a app/Console/Commands folder with Inspire.php in it. The inspire command is called from the scheduler. So if I'd like to schedule a job, should I call a command and then call the job inside this command?
Commands are not jobs. Commands are commands - you can create them and use them via command line. They can, however, be used for scheduling repeated tasks.
In this case - if you need a "job" - the documentation states:
The only Cron entry you need to add to your server is this:
php /path/to/artisan schedule:run 1>> /dev/null 2>&1
After you did that, you are free to use the implementation explained here. Basically, you use the Scheduler to set tasks that will run in whatever iterations you like. Pretty cool, isn't it?
I have two cron jobs for importing image process into Database and scheduled that cron runs per two days once at server time 1 hour 2min. I need to check if the cron runs or not using shell script and kill that cron if the runs that cron already or after two days. Can you anybody guide me?
Example:
2 1 */2 * * cd /var/www/railsapp/book_app_v2 && /usr/local/bin/rake RAILS_ENV=production db:load_java_photo 2>&1 >> /var/www/railsapp/book_app/log/cron_book_photo.log
If I understand you right, you want to prevent cron overruns. Check out hatools, which addresses exactly that issue.
halockrun provides a simple and reliable way to implement a locking in shell scripts. A typical usage for halockrun is to prevent
cronjobs to run simultanously. halockrun's implementation makes it
very resilient to all kind of stale locks.
hatimerun provides a time-out mechanism that can be used from shell scripts. hatimerun can set multiple actions--signals to be
sent--on multiple timeouts.