I am trying to run Laravel Scheduler in Google Cloud.
In my command, I have this
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\User;
use Carbon\Carbon;
class ChangeRole extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'command:update';
/**
* The console command description.
*
* #var string
*/
protected $description = 'This Changes Stuffs';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
//
$users = User::where('trialExpires', '<=', Carbon::now())->get();
foreach ($users as $user) {
$user->type= 'subscriber';
$user->save();
}
}
}
I have done this in my Kernel
protected $commands = [
//
'App\Console\Commands\ChangeRole',
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('command:update')
->daily();
}
In my cron.yaml file
cron:
- description: "daily job"
url: '* * * * * cd /project_id && php artisan command:update >> /dev/null 2>&1'
schedule: every 24 hours
retry_parameters:
min_backoff_seconds: 2.5
max_doublings: 5
timezone: Europe/Madrid
When I ran gcloud app deploy cron.yaml
I got this error
ERROR: (gcloud.app.deploy) An error occurred while parsing file: [C:\xampp1\newlibri\cron.yaml]
Unable to assign value '* * * * * cd /starlit-advice-260914 && php artisan command:update >> /dev/null 2>&1' to attribute 'url':
Value '* * * * * cd /starlit-advice-260914 && php artisan command:update >> /dev/null 2>&1' for url does not match expression '^(?:^/.*$)$'
in "C:\xampp1\newlibri\cron.yaml", line 3, column 8
I don't know what I did wrong.
When I run PHP artisan command:update. The scheduler work just fine. But I am unable to replicate on Google Cloud
I have been able to fix the error.
I have to set the URL to a get request in my application.
cron:
- description: "daily summary job"
url: /api/checksub
schedule: every 24 hours
retry_parameters:
min_backoff_seconds: 2.5
max_doublings: 5
timezone: Europe/Madrid
In my controller, I have this
public function checksub() {
$users = User::where('trialExpires', '<=', Carbon::now())->update(['role'=> 'subscriber']);
));
}
It doesn't need to setup Laravel Scheduler. Just call the get result of the URL
You might want to use the default implementation for these scheduler tasks. Basically what you do is setup a CRON task which runs the scheduler function every minute, and let the PHP code decide whether to run particular tasks.
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
This will run your app\Console\Kernel.php::schedule() function every minute, in which you can then define your tasks like:
// Example function which removes users older than a year.
$schedule->call(function () {
User::query()
->where('created_at', '<', Carbon::now()->subYear())
->delete();
})->hourly();
See https://laravel.com/docs/7.x/scheduling
Related
What I'm intending to do is to make a task scheduling for weekly, which is to copy all of id from table route_schedule and insert into table route_schedule_details as FK, which then will insert the date of the weeks. This is how the route_schedule_details schema:
Schema::create('route_scheduler_details', function (Blueprint $table) {
$table->id();
$table->dateTime('schedule_date')->nullable();
$table->unsignedBigInteger('route_scheduler_mstr_id')->nullable()->index('FK_route_scheduler_details_route_scheduler_mstr');
$table->foreign(['route_scheduler_mstr_id'], 'FK_route_scheduler_details_route_scheduler_mstr')->references(['id'])->on('route_scheduler_mstr')->onDelete('cascade');
});
I never used task scheduling before so I'm little bit under-knowledged here. Read in Laravel docs, I have to add the schedule in App/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
$data = [];
$copies = RouteSchedulerMSTR::select('id')->get();
foreach($copies as $copy){
//I'm not sure what to do in here
}
})->weekly(1, '1:00');
}
Firstly, you need to create command because above your code can't test work or not :
php artisan make:command RouteSchedulerWeekly
<?php
namespace App\Console\Commands;
use App\Models\RouteSchedulerMSTR;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class RouteSchedulerWeekly extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'routeschedule:weekly';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Run route scheduler weekly';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return int
*/
public function handle()
{
$copies = RouteSchedulerMSTR::select('id')->get();
foreach($copies as $copy){
DB::table('route_scheduler_details')->insert([
'data' => now(),
'route_scheduler_mstr_id' => $copy
]);
$this->info('Route scheduler inserting...');
}
$this->info('Done!');
}
}
Then you can test your code insert or not :
php artisan routeschedule:weekly
if you wanted function is correct, you can run by cronjob with 2 options
Direct run command with cron
crontab -e
and add below script to crontab file on your server:
0 1 * * 6 cd /var/www/your-project && php artisan routeschedule:weekly >> /dev/null 2>&1
You can test crontab script here
In Windows use Task Scheduler
OR
Run with schedule:run
Add your command in Kernel
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('routeschedule:weekly')->weekly(1, '1:00');
}
}
and add below script to crontab file on your server:
* * * * * cd /var/www/your-project && php artisan schedule:run >> /dev/null 2>&1
here * * * * * is every minute
Conclusion: I recommend option 1 that will run once in a week on your server. The option 2 also run once in a week your command but schedule:run running every minute
I don't want to set server cron to run every minute (* * * * *) so I set it to #daily
#daily usr/bin/php /home/dss/laravelAppDss/artisan schedule:run >> /home/dss/public_html/example.txt
This is my Kernel.php
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* #var array
*/
protected $commands = [
'\App\Console\Commands\SinkronDataDosen',
'\App\Console\Commands\SinkronDataMahasiswa',
'\App\Console\Commands\SinkronPotensiDO',
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('SinkronDataDosen');
$schedule->command('SinkronDataMahasiswa');
$schedule->command('SinkronPotensiDO');
}
/**
* Register the Closure based commands for the application.
*
* #return void
*/
protected function commands()
{
require base_path('routes/console.php');
}
}
But it doesn't sync the data
This is the output example.txt
Running scheduled command: '/usr/bin/php7.0' 'artisan' SinkronDataDosen > '/dev/null' 2>&1
Running scheduled command: '/usr/bin/php7.0' 'artisan' SinkronDataMahasiswa > '/dev/null' 2>&1
Running scheduled command: '/usr/bin/php7.0' 'artisan' SinkronPotensiDO > '/dev/null' 2>&1
The commands worked if I run each command signature individually so there is nothing wrong with the commands
How do I solve it?
I have a simple set up a command for Scheduling that is firing on a cron call
The artisan command works fine yet nothing happens when Scheduling
The Schedule
protected function schedule(Schedule $schedule)
{
$schedule->command('prices:pricing')
->everyMinute();
}
The Task
protected $signature = 'prices:pricing';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Gets Pricing data and stores in DB';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
Log::debug('An informational message.');
}
}
The cron
* * * * * www-data cd /var/www/api && php artisan schedule:run >> /dev/null 2>&1
Also I have tried with running
php artisan queue:listen
I've to send automated emails to members of my subscription system. When I schedule a job in my laravel project and cron job on my localhost it runs properly every minute. But when I upload the same project to my shared hosting the scheduled task doesn't run. Can anyone help me fix this issue?
My CronTab:
SHELL="/bin/bash"
* * * * * php /home/tradiet1/public_html/tradiedemo/tradiepackage/artisan schdule:run
My NotifyMembershipRenewal:
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Jobs\SendMembershipRenewalNotification;
use App\AppLog;
use Carbon\Carbon;
use App\User;
class NotifyMembershipRenewal extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'notify:membership_renewal';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Send notification email to users informing them their membership subscription is about to expire .';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
$args = request()->server('argv');
$log = new AppLog;
$log->url = url()->current();
$log->details = "Cron started at: ".date('Y-m-d H:i:s')." in dir: ".__DIR__;
$log->details .= "\r\n".' args: '.json_encode($args);
\DB::enableQueryLog();
$now = Carbon::now();
$expiryInDays = 7;
$from = $now->addDays($expiryInDays-1)->format('Y-m-d H:i:s');
$to = $now->addDay()->format('Y-m-d H:i:s');
$users = User::with('membership')
->where('role', 3)
->whereBetween('membership_expiry', [$from, $to])
->get();
foreach($users as $key => $user)
{
dispatch(new SendMembershipRenewalNotification($user, $expiryInDays));
}
$log->details .= "\r\n Count: ".$users->count();
$log->details .= "\r\n ".json_encode(\DB::getQueryLog())."\r\n \r\n";
$log->save();
$this->info($log->details);
}
}
My Kernel.php:
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use App\AppLog;
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)
{
$log = new AppLog;
$log->details = "Inside Kernel#schedule";
$log->save();
$schedule->command('notify:membership_renewal')
->everyMinute() // 22:00 UTC = 08:00 AEST
->appendOutputTo('./app_log.txt')
->emailOutputTo(env('APP_LOG_EMAIL'));
/*$schedule->command('inspire')
->hourly();*/
}
/**
* Register the commands for the application.
*
* #return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
My Crontab for localhost:
SHELL="/bin/bash"
* * * * * php /var/www/html/is/tradiedemo/tradiepackage/artisan schedule:run
My Crontab for my live shared hosting server
SHELL="/bin/bash"
* * * * * php /home/tradiet1/public_html/tradiedemo/tradiepackage/artisan schdule:run
The cron jobs run normally on my localhost and I get email every minute and log is stored in the DB as well as file. But when I transfer the project to my server the cron job runs every minute but the scheduled task doesn't run every minute. The task doesn't run even once.
In Shared Hosting you can't run a cron job every minute. because of it's a limitation on shared hosting(In Godaddy or Hostgator I guess). so you can do like run every 30 min every 15 min.
You read it about here too Cron Job in hostgator
But ya some Hosting provider provide this facility too.
So now the question is why it's not running right.
Its happened with me too. there is some issue with register_argc_argv but sometimes setting it on also not work so best practice rather than do it with PHP.
You can do this with pho-cli that's it.
Definitely it will work.
Do it like below
SHELL="/bin/bash"
* * * * * php-cli -q /home/tradiet1/public_html/tradiedemo/tradiepackage/artisan schdule:run
Hope it works for you.
Update
So as you said it does not work for you. so there is a rough solution for this is.
why not you do a cron on URL which is quite easy and work on any shared hosting and Cpanel things.
so for this, you can use wget for url. Below is the code related to it.
wget http://example.com/check
and now on your route function run your artisan programmatically something like below.
Route::get('/check', function () {
Artisan::call('schedule:run');
});
I have a very large cron job that need to be carry out, but server cannot handle it due to memory leaks, so i follow the suggestion to use laravel Queue, and because i can't always run php artisan queue:work, so i wrote a scheduled queue command that trigger every 5 minutes, but the queue not working unless i manual trigger it on server.
Here is my command for queue:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class EnsureQueueListenerIsRunning extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'queue:checkup';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Ensure that the queue listener is running.';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
//
$this->startQueueListener();
if ( ! $this->isQueueListenerRunning()) {
$this->comment('Queue listener is being started.');
$pid = $this->startQueueListener();
$this->saveQueueListenerPID($pid);
}
$this->comment('Queue listener is running.');
}
/**
* Check if the queue listener is running.
*
* #return bool
*/
private function isQueueListenerRunning()
{
if ( ! $pid = $this->getLastQueueListenerPID()) {
return false;
}
$process = exec("ps -p $pid -opid=,cmd=");
//$processIsQueueListener = str_contains($process, 'queue:listen'); // 5.1
$processIsQueueListener = ! empty($process); // 5.6 - see comments
return $processIsQueueListener;
}
/**
* Get any existing queue listener PID.
*
* #return bool|string
*/
private function getLastQueueListenerPID()
{
if ( ! file_exists(__DIR__ . '/queue.pid')) {
return false;
}
return file_get_contents(__DIR__ . '/queue.pid');
}
/**
* Save the queue listener PID to a file.
*
* #param $pid
*
* #return void
*/
private function saveQueueListenerPID($pid)
{
file_put_contents(__DIR__ . '/queue.pid', $pid);
}
/**
* Start the queue listener.
*
* #return int
*/
private function startQueueListener()
{
//$command = 'php-cli ' . base_path() . '/artisan queue:listen --timeout=60 --sleep=5 --tries=3 > /dev/null & echo $!'; // 5.1
$command = 'php artisan queue:work --timeout=60 --sleep=5 --tries=3 > /dev/null & echo $!'; // 5.6 - see comments
$pid = exec($command);
return $pid;
}
}
Here is the kernel:
$schedule->command('queue:checkup')->everyFiveMinutes();
What should i do to make it work?
if you want to set the crone job to run automatically without initiating using command.**
go to your terminal: and run this command
crontab -e
This will open server crontab file, paste this code inside, save it and exit
* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1