Cake PHP run multiple Console/cake shell commands in different processes - php

I've written a Console/cake shell for my Cake PHP 2 project. My shell is called a Queue Manager, and it contains two tasks, a ProcessTask.php and a ScheduleRunTask.php, it's my ProcessTask that once ran will grab entries from a database table, loop over them and do something. I cannot use Supervisor for the project I'm working on as this is a strict prerequisite.
The issue I face is that I need it to run automatically, and ideally need it to automatically scale up and down based on a settings table setting called something like "max workers" so that it's not always running 10 commands at once when it doesn't need to.
I've put together a crontab which runs my scheduler once a minute:
* * * * * cd /path-to-project-app && Console/cake queue_manager schedule_run >> /dev/null 2>&1
When this runs the schedule_run task, this in turn fires up the process task and runs these:
<?php
class ScheduleRunTask extends AppShell {
/**
* Main execute task
*/
public function execute() {
$maxWorkers = 5;
$currentWorker = 0
while ($currentWorker < $maxWorkers) {
exec("cd /path-ro-my-project-app && Console/cake queue_manager process", $output, $retval);
$this->out("<info>Worker is running.</info>");
}
}
}
But is this the best way to do this and do these run in their own processes? Which is important.
How do I prevent it from starting up another 5 exec commands on the next minute the cron runs, I'd end up with hundreds right?

Related

Why it cant loop the function every 5 minutes? (cronjob, task scheduling laravel)

I'm trying to set up a scheduling task that can run every five minutes, but it only works 1 time, after the first five minutes, the other five minutes dont do the function correctly.
//depresiasicounter.php
protected $signature = 'updates:depresiasicounter';
public function handle()
{
$aktivatb = Aktivatb::where('id','1')->first();
$aktivatb->nilai= $aktivatb->nilai-$aktivatb->depresiasi;
$aktivatb->total_depresiasi = $aktivatb->total_depresiasi+$aktivatb->depresiasi;
$aktivatb->save();
}
//kernel.php
protected $commands = [
Commands\DepresiasiCounter::class,
];
protected function schedule(Schedule $schedule)
{
$schedule->commands('updates:depresiasicounter')->everyFiveMinutes();
}
I expect it can be work until the value of $aktivatb->nilai to 0, but it only works 1 time
A Scheduled task is basically the system is running a command
php /project-path/artisan schedule:run
every given amount of time.
In Linux environment, people use cron to handle this by creating a crontab
* * * * * php /project-path/artisan schedule:run
Those asterisk signs in front of the command indicates the interval of the
command.
In Windows environment, you can refer to the following answer.
Or you can setup a virtual machine and run the cron job inside the machine.
You need to setup cron so it could run the php artisan schedule:run command every minute, so you need to add the following Cron entry 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.
When using the scheduler, you only need to add the following Cron entry to your server.

Laravel Schedule Call Helper Function Not Working

I'm trying to run a Helper function (App\Helpers) on a scheduled timer using Laravel (for testing purposes I have it running once every minute). I'm using Laravel 5.3.
This is my schedule function in my Kernel.php...
protected function schedule(Schedule $schedule)
{
$schedule->call(function()
{
// Calling this function should write a new file with a random number in it.
// I know this works perfectly fine outside of the scheduled task because I
// call it in other places, and it works)
FileEdit::UpdateFile();
})->everyMinute();
}
The issue is that the FileEdit::UpdateFile() part is NOT ever being called by the laravel at the designated time intervals.
Are you running a cron job to execute the schedule command every minute?
https://laravel.com/docs/5.5/scheduling#introduction
* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
This Cron will call the Laravel command scheduler every minute. When the schedule:run command is executed, Laravel will evaluate your scheduled tasks and runs the tasks that are due.
Your code looks fine, assuming you have cron configured correctly, this may help you debug your issue https://laravel.com/docs/5.5/scheduling#task-hooks
Still I would double check if your cron is working, and set according to https://laravel.com/docs/5.5/scheduling#introduction

How to run cron job in php

I have php function that I wnat to run every 15 minutes. I found some questions like this:
How can I make a cron to execute a php script?
and in my case I should use this:
*/15 * * * * /usr/local/bin/php -q /path/to/my/file.p
But should I run this command in terminal or put it in my file? And once, it is executed, will it run all the time or will have time limit?
Thanks!
PHP doesn't run cron jobs, your server (or operating system) is doing this. There are two ways to put your cron job to work:
#1
Using the shell command crontab. The command crontab -l will list all existing cronjobs for your user (most likely there are none yet). crontab -e will open an editor window where you can put in a you cron job as a new line. Save, and your cron job is now running. crontab -l again and you will see it listet. crontab -r to remove all the cont jobs.
You can also start a cron job from a file. Simply type crontab filename (eg. crontab textfile.txt)
Alternatively you can also start it from within PHP. Just put your cron job into a file and start it via exec() like so:
file_put_contents( 'textfile.txt', '*/15 * * * * /usr/local/bin/php -q /path/to/my/file.php' );
exec( 'crontab textfile.txt' );
#2
If you have admin privileged on your system you can create a file in /etc/cron.d/ (for example, call it my_cronjob) and put your cron job there. In this case you probably want to run it as a user (not as admin, that would be rather insecure). This is quite easy to do, just add the user name like so:
*/15 * * * * user_name /usr/local/bin/php -q /path/to/my/file.p
(In this case the cron job will not be listet under crontab -l)
Answering your second question: As long as the cron job is listet in crontab -l or as long as the file is sitting in /etc/cron.d the cron job is running, in your case, every 15 minutes.
10 * * * * /usr/bin/php /www/virtual/username/cron.php > /dev/null 2>&1
There are two main parts:
The first part is "10 * * * *". This is where we schedule the timer.
The rest of the line is the command as it would run from the command line.
The command itself in this example has three parts:
"/usr/bin/php". PHP scripts usually are not executable by themselves. Therefore we need to run it through the PHP parser.
"/www/virtual/username/cron.php". This is just the path to the script.
"> /dev/null 2>&1". This part is handling the output of the script. More on this later.
Please read this tutorial http://code.tutsplus.com/tutorials/scheduling-tasks-with-cron-jobs--net-8800

Laravel "No scheduled commands are ready to run."

I've set up the following Laravel commands on the App\Console\Kernel:
protected function schedule(Schedule $schedule) {
$schedule->command('command:daily-reset')->daily();
$schedule->command('command:monthly-reset')->monthly();
}
Then, on my server, I've set up a cron job to run once per day (at 00:00).
0 0 * * * php /home/privates/public_html/staging/current/artisan schedule:run
My cron job is running successfully each night, but the logs simply say: "No scheduled commands are ready to run."
What am I doing wrong? I would expect my daily command to run each night.
Thanks!
When you run
php artisan schedule:run
in the server, where your project is stored, you could see all of your commands running with output, looking like this:
"Running scheduled command: '/usr/local/bin/php' 'artisan' cache:update > '/dev/null' 2>&1 &"
but only if the current time is the exact one, for which the command is scheduled. Otherwise you are going to see this output:
"No scheduled commands are ready to run."
For example, if you schedule the command for every five minutes and run the command in 09:07 o'clock you will see that there are no scheduled commands, but if you run it in 09:10 you will see your command running.
In this way you can just schedule your command to run every 5 min just for debugging purposes:
$schedule->command('command:daily-reset')->everyFiveMinutes();
then observe if there is any error while running and eventually fix it. By me the problem was that I haven't installed GuzzleHttp (shame), so the fix was just running this in the terminal:
composer require guzzlehttp/guzzle
I realized that the problem for me was the below chained method:
->withoutOverlapping()
Once I removed that method, my commands started running and being found by the daemon process.
I think there might be a bug with the method, but my project for now can take a bit overlapping so it's cool.
Did you try running command manually?
Run php artisan and see if your commands have registered.
If you have registered your commands you should see command:daily-reset and command:monthly-reset under the list of available artisan commands.
If you don't see them there go ahead and register your commands by adding it to commands property available in app/Console/Kernel.php.
protected $commands = [
'App\Console\Commands\YourFirstCommand',
'App\Console\Commands\YourSecondCommand'
];
Change crontab entry to
* * * * * php /home/privates/public_html/staging/current/artisan schedule:run
The Laravel scheduled commands are based in the timezone that you have configured in your app/config/app.php file (laravel 5.1):
/*
|--------------------------------------------------------------------------
| Application Timezone
|--------------------------------------------------------------------------
|
| Here you may specify the default timezone for your application, which
| will be used by the PHP date and date-time functions. We have gone
| ahead and set this to a sensible default for you out of the box.
|
*/
'timezone' => 'America/Bogota',
So if you create a command and register it to run as a scheduled task with:
$schedule->command('command:daily-reset')->daily();
it will run every day at 00:00 OF THE TIMEZONE SPECIFIED (in this case America/Bogota)
The same thing applies if you specify a time to run the task:
$schedule->command('command:daily-reset')->daily()->at('02:30');
This will run at 02:30 am in America/Bogota local time.
NB: This is not answer for this question, but a clue for anyone debugging with php artisan schedule:run manually. Hope it saves someone a few minutes of headache.
Check if the scheduled task can run immediately. You can use the exec method for that.
<?php
//...
protected function schedule (Schedule $schedule) {
$schedule->exec("php artisan your:command");
}
The reason for this is that, you might be scheduling the task to run at a certain time and if that time isn't due yet, it will output:
No scheduled commands are ready to run.
The full answer to this question is not listed above as far as I can see. Let's assume that our schedule is as follows:
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.
However, this doesn't quite address your issue, given that the daily() schedule (0 0 * * *) aligns with your cron-job schedule. The only thing I can imagine is that there is some kind of misalignment with your time-zones as suggested by #Octavio Herrera. But that's difficult to say without knowing a bit more about your environment.
I had the same problem. Every command was correctly registered but I always received the “No scheduled commands are ready to run.” message. The problem was that the website was in "maintenance mode" (php artisan down command) while we were doing updates and tests.
I think that my blog will help you answer your question. Please see the below or link: Laravel Crontab
In many projects, you need use crontab (cron jobs) to execute some tasks as sending email or delete waste record in DB. With Laravel Project, you can do this easier.
Create a command in Laravel 4:
<?php
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
class FirstCommand extends Command {
/**
* The console command name.
*
* #var string
*/
protected $name = 'user:active';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Command description.';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function fire()
{
echo "User Actived";
}
/**
* Get the console command arguments.
*
* #return array
*/
protected function getArguments()
{
return array(
);
}
/**
* Get the console command options.
*
* #return array
*/
protected function getOptions()
{
return array(
array('example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null),
);
}
}
Next step, you need to register the command with Laravel CLI. So easy, you open app/start/artisan.php file, and add one line as below:
Artisan::add(new FirstCommand);
You are done creating Laravel Command. To test, you could use command below:
$ php artisan user:active
User Active
The output above mean you successfully register a command.
Finally, put your command into the crontab:
crontab -e
Add line (run command every 2 minutes):
*/2 * * * * php path_to_laravel_project/artisan user:active
That’s all. Thank you for talking time to read this.
On Windows, I fixed this issue by setting the Scheduled Task to run every minute (even though I only wanted to trigger a command once per day), otherwise I always got the No scheduled commands are ready to run. message.
Since I still ran into this issue 4 years later (2019) and a different workaround worked for me, I think it is worth hinting the simple step that solved for me, which is: Use a shorter interval first.
That seems to just wake it up to handle longer intervals in some ways. I had everyFiveMinutes() and for almost 2 hours it was getting the No scheduled commands are ready to run response. I simply changed it to everyMinute() and it started running correctly. I watched it consistently for like 10 minutes or so, then changed it back to everyFiveMinutes() and it all went smoothly.
I've stuck with this problem No scheduled commands are ready to run. for an hours, but solve it easly:
Problem was with rights to folder storage.
So, i've set chmod -R 777 storage/* (i'm not sure is this is elegant way).
After that cron starts working properly.
To run the Cron Commands on the local server, follow these steps:
I know you have already mentioned the command in app/console/Kernel.php
Now open the command line, enter "crontab -e"
Edit that file and mention the below code(without quote) to keep running PHP artisan schedule:run in the background
"* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1"
Enter "crontab -l" in the command line, it will list running crons
Done !!
Now, wait for cron to process your command. Cheers!!
Reference- https://laravel.com/docs/7.x/scheduling#introduction
For whatever reason cron does not recognize the named version of your task.
So in your schedule instead of writing
$schedule->command('command:task');
you should use the path of the class, such as
$schedule->command(\App\Console\Commands\TASK::class)
...the same goes for the scheduler on Laravel Forge!
I have tried everything but finally I found a solution for this problem. Add the timestamp in the command. Below is the example for this.
$schedule->call(function(){
print("HELLO");
})->dailyAt('21:51')->timezone('Asia/Kolkata');
or
$schedule->command('tenam:before')
->dailyAt('22:28')->timezone('Asia/Kolkata');
Try
php artisan cache:clear
and then run scheduler again with
php artisan schedule:run
I was also facing same issue and it resolved my problem.

Create a cron job with user define dtime

I want to create a cron job which will run with the user define time in database.
For eg.User can set start time and end time in the database .When the end time is reached I want cron to trigger one script to send mail.First of all Is it possible in cron or I have to go with some different approach ? and this all things will be done on AWS EBS.
Below is what I tried on my local machine to just send a simple mail which is too basic
*/1 * * * * /usr/bin/php -q/var/www/html/cronTry/cron.php
You dont want to run the CRON every minute instead create a specific job for your user and run it once. Something like this should work (untested - on mobile)
$your_users_date;
$cmd = "sudo crontab -l | { cat; echo ". date("i H d m",strtotime($your_users_date))." * php /path_to_your_script.php arg1 arg2; } | crontab -";
shell_exec($cmd);
This will append a job to the crontab at the time your user has defined
Get the dynamic details from the database, create the command string and
You can easily run your cron by passing the command in the shell_exec()

Categories