Laravel applications often need scheduled tasks for things like sending reminders, generating reports, clearing old data, processing renewals, or running automated commands.
On a VPS, you can usually configure cron jobs directly through SSH. On shared hosting, the process is slightly different because you normally use the hosting control panel.
This guide explains how to set up Laravel cron jobs on shared hosting using Laravel's built-in scheduler.
What Is a Cron Job?
A cron job is a command that runs automatically at a scheduled time.
For example, you may want your application to:
Send invoice reminders every morning
Process subscriptions every hour
Delete temporary files every night
Generate reports every day
Send scheduled emails
Check expired accounts
Run database cleanup tasks
Instead of manually running these commands, cron can run them automatically.
How Laravel Scheduler Works
Laravel includes its own task scheduler.
Instead of creating a separate server cron job for every Laravel task, you normally create only one server cron job.
That cron job runs:
php artisan schedule:runLaravel then checks your application schedule and decides which tasks should run.
The Laravel documentation recommends running the scheduler every minute using a single cron entry.
Basic Laravel Cron Command
A standard Laravel cron entry looks like:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1This runs every minute.
Laravel checks the scheduled tasks defined inside the application and runs only the tasks that are due.
Example Laravel Project Location
Suppose your Laravel application is installed here:
/home/username/public_htmlYour Artisan file would be:
/home/username/public_html/artisanA possible cron command would be:
cd /home/username/public_html && php artisan schedule:run >> /dev/null 2>&1Do not copy this path blindly.
Use the actual path to your Laravel project.
Step 1: Find Your Laravel Project Path
If you have SSH access, go to your project:
cd /home/username/public_htmlThen run:
pwdYou may see something like:
/home/username/public_htmlYou can also check that the Artisan file exists:
ls -l artisanIf artisan appears, you are probably in the correct Laravel project directory.
Step 2: Find the Correct PHP Path
On shared hosting, simply running:
phpmay not always use the same PHP version as your website.
Check the command-line PHP version:
php -vYou may see:
PHP 8.3.xor another version.
You can also find the PHP executable using:
which phpFor example:
/usr/bin/phpSome hosting companies use version-specific binaries such as:
/usr/local/bin/php83or:
/usr/bin/php8.3The correct path depends on your server.
Step 3: Test Laravel Scheduler Manually
Before creating the cron job, test the command manually.
Go to your Laravel directory:
cd /home/username/public_htmlRun:
php artisan schedule:runIf everything is working, Laravel may display a message showing which tasks were executed.
If no scheduled tasks are currently due, it may complete without running anything.
Step 4: Check the Laravel Schedule
In current Laravel versions, scheduled tasks can be defined in:
routes/console.phpFor example:
<?php
use Illuminate\Support\Facades\Schedule;
Schedule::command('emails:send')->daily();Laravel supports scheduling commands at different intervals such as every minute, hourly, daily, weekly, and more.
Example: Run a Command Every Minute
use Illuminate\Support\Facades\Schedule;
Schedule::command('orders:check')->everyMinute();Your server cron still runs:
php artisan schedule:runevery minute.
Laravel determines whether orders:check should run.
Example: Run Every Five Minutes
Schedule::command('notifications:send')->everyFiveMinutes();Example: Run Every Hour
Schedule::command('reports:generate')->hourly();Example: Run Every Day
Schedule::command('database:cleanup')->daily();Example: Run at a Specific Time
Schedule::command('reports:send')->dailyAt('08:00');This schedules the command for 8:00 AM according to the application's configured scheduling timezone.
Step 5: Create the Cron Job in Your Hosting Panel
Open your hosting control panel.
Look for:
Cron Jobs
Scheduled Tasks
Task Scheduler
Cron Manager
The exact name depends on your hosting provider.
Create a new cron job.
Set it to run every minute.
Typical cron timing:
Minute: *
Hour: *
Day: *
Month: *
Weekday: *Then enter the Laravel command.
Example:
cd /home/username/public_html && /usr/bin/php artisan schedule:run >> /dev/null 2>&1Save the cron job.
Alternative Cron Command Using Full Artisan Path
You can also use:
/usr/bin/php /home/username/public_html/artisan schedule:run >> /dev/null 2>&1This avoids using the cd command.
Both approaches can work.
Recommended Laravel Cron Command
A clean command is:
cd /home/username/public_html && /usr/bin/php artisan schedule:run >> /dev/null 2>&1Replace:
/home/username/public_htmlwith your actual Laravel application path.
Also replace:
/usr/bin/phpif your hosting server uses a different PHP binary.
Why Does Laravel Cron Run Every Minute?
You may wonder why the server cron runs every minute even if your Laravel task only runs once per day.
Laravel uses one scheduler command:
php artisan schedule:runThe command checks whether any scheduled Laravel tasks are due at that moment.
For example:
Schedule::command('reports:send')->dailyAt('08:00');The server cron runs every minute, but Laravel only executes reports:send when the configured schedule says it should run. This single-entry approach is the standard Laravel scheduler setup.
How to Check Your Scheduled Laravel Tasks
You can inspect your Laravel application's schedule using:
php artisan schedule:listThis can show your scheduled commands and their next expected run times.
It is useful when troubleshooting why a task is not running.
Create a Test Laravel Command
If you want to confirm your cron configuration works, create a simple Artisan command.
Run:
php artisan make:command CronTestLaravel will create a command class.
Add simple logging inside the command.
For example:
use Illuminate\Support\Facades\Log;
public function handle()
{
Log::info('Laravel cron test executed');
return 0;
}Then schedule the command:
Schedule::command('app:cron-test')->everyMinute();The exact command signature depends on the command you create.
After saving the code, wait for the cron job to run.
Then check:
storage/logs/laravel.logYou should see your test message.
Simple Cron Test Using a Closure
You can also add a temporary scheduler test:
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schedule;
Schedule::call(function () {
Log::info('Laravel scheduler is working');
})->everyMinute();Then check:
storage/logs/laravel.logOnce testing is complete, remove the temporary test schedule.
Cron Job Runs Manually but Not Automatically
This is a common shared-hosting problem.
If this works:
php artisan schedule:runbut the cron job does not run automatically, check the following.
Check the Cron Path
Make sure the Laravel project path is correct.
Incorrect:
/home/user/publicwhen the actual application is:
/home/user/public_htmlCheck the PHP Binary
Your cron environment may not know where PHP is located.
Instead of:
php artisan schedule:runtry using the full PHP path:
/usr/bin/php artisan schedule:runCheck PHP Version
Your website may use PHP 8.3 while cron uses PHP 8.1.
Run:
php -vand compare it with the PHP version configured for the website.
If necessary, use the correct version-specific binary.
Cron Shows "Could Not Open Input File: artisan"
You may see:
Could not open input file: artisanThis means cron is not running from the Laravel project directory.
Use:
cd /home/username/public_html && php artisan schedule:runor specify the complete Artisan path:
php /home/username/public_html/artisan schedule:runCron Shows "php: command not found"
The cron environment may not have PHP in its PATH.
Find PHP:
which phpThen use the complete path:
/usr/bin/php /home/username/public_html/artisan schedule:runCron Uses the Wrong PHP Version
Check available binaries:
ls /usr/bin/php*or ask your hosting provider for the correct CLI PHP path.
You may need something similar to:
/usr/bin/php8.3 artisan schedule:runThe exact path differs between servers.
Laravel Cron Returns Permission Denied
Check the Laravel folder and file permissions.
Laravel needs write access to:
storage/
bootstrap/cache/You may need:
chmod -R 775 storage
chmod -R 775 bootstrap/cacheFile ownership also matters.
If the files belong to a different system user, permissions alone may not solve the problem.
Cron Cannot Write Laravel Logs
If cron runs as a different user, Laravel may fail to write:
storage/logs/laravel.logCheck ownership:
ls -la storage/logsMake sure the cron user can write to the Laravel storage directory.
Laravel Cron Has Database Errors
Cron uses the same Laravel application configuration as your website.
Check:
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=your_database
DB_USERNAME=your_user
DB_PASSWORD=your_passwordIf the application configuration has been cached, clear it after modifying .env:
php artisan optimize:clearCron Uses Old .env Values
Laravel may have cached an older configuration.
Run:
php artisan optimize:clearThen test:
php artisan schedule:runOnce everything works, you can run:
php artisan optimizefor your production deployment.
How to Save Cron Output for Troubleshooting
During troubleshooting, do not immediately send all output to /dev/null.
Instead of:
php artisan schedule:run >> /dev/null 2>&1use:
php artisan schedule:run >> /home/username/cron.log 2>&1Then inspect:
cat /home/username/cron.logor:
tail -f /home/username/cron.logThis can reveal PHP errors, incorrect paths, permission errors, and missing extensions.
Once the cron job works correctly, you can disable or rotate the debug log.
Why Use >> /dev/null 2>&1?
This part:
>> /dev/null 2>&1discards normal output and error output.
It is useful after the cron job is confirmed to be working because it prevents unnecessary output from accumulating.
While troubleshooting, logging to a file is usually better.
Prevent Laravel Scheduled Tasks from Overlapping
Suppose a job runs every five minutes but sometimes takes ten minutes to complete.
Without protection, another instance may start while the previous one is still running.
Laravel provides:
Schedule::command('reports:generate')
->everyFiveMinutes()
->withoutOverlapping();Laravel uses a cache-based lock to prevent another instance of that scheduled task from starting before the previous instance finishes.
This is useful for:
Invoice generation
Large reports
API synchronization
Data imports
Email campaigns
Run a Task on One Server Only
If your Laravel application runs on multiple servers, a scheduled task could run once on every server.
Laravel supports:
Schedule::command('reports:generate')
->daily()
->onOneServer();This is useful in multi-server environments.
A supported shared cache backend is required for the coordination mechanism.
Running Commands in the Background
Long-running commands can delay other scheduled tasks.
Laravel supports:
Schedule::command('reports:generate')
->daily()
->runInBackground();The runInBackground option is supported for scheduled command and exec tasks.
Whether background execution works correctly can also depend on your hosting environment.
Laravel Queue vs Scheduler
Laravel queues and Laravel scheduler are different systems.
The scheduler decides when a task should start.
Queues process jobs asynchronously.
For example:
Schedule::command('invoices:prepare')->daily();could dispatch jobs to a queue.
Those jobs then require a queue worker.
A cron job running:
php artisan schedule:rundoes not automatically replace a queue worker.
Running Queue Jobs on Shared Hosting
On a VPS, you may use a process manager to keep:
php artisan queue:workrunning continuously.
Basic shared hosting may not allow a permanent process.
One possible shared-hosting approach for simple workloads is to run a queue worker through cron using options that allow it to exit after processing available work.
However, queue configuration depends heavily on the application and hosting environment.
Applications that rely on continuous queues may be better suited to a VPS.
Scheduler vs Normal Cron Jobs
You could create server cron jobs such as:
0 8 * * * php artisan reports:sendbut Laravel Scheduler usually provides cleaner application management.
With Laravel Scheduler:
Schedule::command('reports:send')->dailyAt('08:00');and the server needs only:
* * * * * php artisan schedule:runYour application schedule stays inside your source code.
Laravel Scheduler Timezone
The server timezone and application timezone may not always match.
Check:
APP_TIMEZONE=Asia/Colomboor the timezone setting used by your Laravel version and application configuration.
You can also configure timezones for scheduled tasks where appropriate.
Laravel's documentation notes that timezone scheduling needs care in regions affected by daylight saving time because tasks may run twice or be skipped during clock changes.
Sri Lanka does not currently use daylight saving time, but your server or application may still be configured to another timezone.
Check Server Time
Run:
dateCompare this with your application's expected timezone.
If your task is supposed to run at:
08:00 AMbut your server runs UTC, the actual execution time may differ unless Laravel's timezone configuration accounts for it.
Cron Job Example for cPanel
A typical cPanel cron setup may use:
Minute: *
Hour: *
Day: *
Month: *
Weekday: *Command:
cd /home/username/public_html && /usr/local/bin/php artisan schedule:run >> /dev/null 2>&1Your PHP path may differ.
Cron Job Example for aaPanel
If your Laravel project is:
/www/wwwroot/example.coma command may look like:
cd /www/wwwroot/example.com && /usr/bin/php artisan schedule:run >> /dev/null 2>&1Some aaPanel installations use PHP binaries inside version-specific directories.
Use the PHP executable configured on your server.
Cron Job Example for a Laravel App in a Subfolder
Suppose your project is:
/home/user/apps/invoice-systemUse:
cd /home/user/apps/invoice-system && /usr/bin/php artisan schedule:run >> /dev/null 2>&1The directory containing the artisan file is the Laravel project root.
Common Laravel Cron Mistake: Pointing to Public Folder
Do not normally run:
cd /home/user/public_html/public && php artisan schedule:runbecause Laravel's artisan file is normally one level above public.
Correct:
cd /home/user/public_html && php artisan schedule:runassuming your project root is public_html.
Common Laravel Cron Mistake: Running index.php
You do not need to execute:
public/index.phpfor the Laravel scheduler.
Use Artisan:
php artisan schedule:runThe HTTP entry point and command-line entry point serve different purposes.
Common Laravel Cron Mistake: Creating One Cron per Task
If you use Laravel Scheduler, you generally do not need separate server cron entries for every task.
You can define:
Schedule::command('emails:send')->hourly();
Schedule::command('subscriptions:check')->daily();
Schedule::command('reports:generate')->weekly();while keeping one server cron:
* * * * * php artisan schedule:runThis is one of the main benefits of Laravel's scheduler.
Laravel Cron Troubleshooting Checklist
If your Laravel scheduler is not running, check:
Correct Laravel project path
Correct PHP CLI path
Correct PHP version
Cron configured for every minute
artisanfile existsphp artisan schedule:runworks manuallyScheduled task is actually due
Application timezone
Server timezone
.envconfigurationCached configuration
Database connectivity
Storage permissions
Laravel logs
Cron output logs
Useful Commands
Check PHP:
php -vFind PHP:
which phpCheck project directory:
pwdTest Laravel:
php artisanRun scheduler manually:
php artisan schedule:runView the schedule:
php artisan schedule:listClear Laravel cache:
php artisan optimize:clearCheck Laravel logs:
tail -f storage/logs/laravel.logRecommended Production Cron Setup
A typical production setup may look like:
* * * * * cd /home/username/laravel-app && /usr/bin/php artisan schedule:run >> /dev/null 2>&1Laravel then handles your application schedule internally.
For example:
use Illuminate\Support\Facades\Schedule;
Schedule::command('invoices:remind')
->dailyAt('08:00')
->withoutOverlapping();
Schedule::command('reports:generate')
->dailyAt('23:00');
Schedule::command('subscriptions:check')
->hourly();This keeps your scheduling logic inside your Laravel application instead of maintaining many separate server cron entries.
Frequently Asked Questions
How do I run Laravel cron on shared hosting?
Create a server cron job that runs Laravel's scheduler every minute:
cd /path/to/laravel && php artisan schedule:runUse your actual project and PHP paths.
How often should Laravel schedule execute?
Laravel recommends running it once every minute. The scheduler then determines which application tasks are actually due.
Why is my Laravel cron not working?
Common causes include:
Wrong PHP path
Wrong project path
Wrong PHP version
Permission problems
Incorrect timezone
Cached configuration
Task is not currently due
Run the scheduler manually and save cron output to a log file to identify the actual error.
Does Laravel cron require SSH?
No.
You can normally create the cron job from your hosting control panel.
SSH is useful for testing commands and troubleshooting.
Can I run Laravel cron every five minutes?
The server-side Laravel scheduler is normally run every minute.
Inside Laravel, configure the specific task:
Schedule::command('example:command')->everyFiveMinutes();What is the difference between cron and Laravel scheduler?
Cron runs commands according to the server schedule.
Laravel Scheduler lets your application define its own task timings while the server runs only one scheduler cron entry.
Does Laravel cron run when my website is closed?
Yes.
Cron is executed by the server, not by a visitor's browser.
Your website does not need to be open for the scheduler to execute.
Do Laravel queue jobs run automatically with schedule?
Not necessarily.
The scheduler can dispatch queued jobs, but the queue still needs an appropriate worker or processing method.
Laravel Hosting with Ceylon Web Servers
Laravel applications may require more than simply uploading PHP files.
Depending on your project, you may need:
Compatible PHP versions
MySQL databases
Cron jobs
Composer
SSH access
Storage permissions
Queue processing
SSL
Additional server resources
Ceylon Web Servers provides hosting options for websites and web applications.
Available services include:
Shared Hosting
Reseller Hosting
VPS Hosting
Applications requiring continuous background processes, custom server configuration, or greater server control may be better suited to VPS Hosting.
Website: ceylonwebservers.com
Call / WhatsApp: 070 244 7722