How to Set Up Laravel Cron Jobs on Shared Hosting

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:run

Laravel 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>&1

This 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_html

Your Artisan file would be:

/home/username/public_html/artisan

A possible cron command would be:

cd /home/username/public_html && php artisan schedule:run >> /dev/null 2>&1

Do 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_html

Then run:

pwd

You may see something like:

/home/username/public_html

You can also check that the Artisan file exists:

ls -l artisan

If artisan appears, you are probably in the correct Laravel project directory.

Step 2: Find the Correct PHP Path

On shared hosting, simply running:

php

may not always use the same PHP version as your website.

Check the command-line PHP version:

php -v

You may see:

PHP 8.3.x

or another version.

You can also find the PHP executable using:

which php

For example:

/usr/bin/php

Some hosting companies use version-specific binaries such as:

/usr/local/bin/php83

or:

/usr/bin/php8.3

The 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_html

Run:

php artisan schedule:run

If 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.php

For 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:run

every 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>&1

Save 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>&1

This 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>&1

Replace:

/home/username/public_html

with your actual Laravel application path.

Also replace:

/usr/bin/php

if 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:run

The 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:list

This 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 CronTest

Laravel 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.log

You 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.log

Once 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:run

but 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/public

when the actual application is:

/home/user/public_html

Check the PHP Binary

Your cron environment may not know where PHP is located.

Instead of:

php artisan schedule:run

try using the full PHP path:

/usr/bin/php artisan schedule:run

Check PHP Version

Your website may use PHP 8.3 while cron uses PHP 8.1.

Run:

php -v

and 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: artisan

This means cron is not running from the Laravel project directory.

Use:

cd /home/username/public_html && php artisan schedule:run

or specify the complete Artisan path:

php /home/username/public_html/artisan schedule:run

Cron Shows "php: command not found"

The cron environment may not have PHP in its PATH.

Find PHP:

which php

Then use the complete path:

/usr/bin/php /home/username/public_html/artisan schedule:run

Cron 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:run

The 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/cache

File 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.log

Check ownership:

ls -la storage/logs

Make 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_password

If the application configuration has been cached, clear it after modifying .env:

php artisan optimize:clear

Cron Uses Old .env Values

Laravel may have cached an older configuration.

Run:

php artisan optimize:clear

Then test:

php artisan schedule:run

Once everything works, you can run:

php artisan optimize

for 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>&1

use:

php artisan schedule:run >> /home/username/cron.log 2>&1

Then inspect:

cat /home/username/cron.log

or:

tail -f /home/username/cron.log

This 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>&1

discards 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:run

does 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:work

running 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:send

but 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:run

Your application schedule stays inside your source code.

Laravel Scheduler Timezone

The server timezone and application timezone may not always match.

Check:

APP_TIMEZONE=Asia/Colombo

or 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:

date

Compare this with your application's expected timezone.

If your task is supposed to run at:

08:00 AM

but 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>&1

Your PHP path may differ.

Cron Job Example for aaPanel

If your Laravel project is:

/www/wwwroot/example.com

a command may look like:

cd /www/wwwroot/example.com && /usr/bin/php artisan schedule:run >> /dev/null 2>&1

Some 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-system

Use:

cd /home/user/apps/invoice-system && /usr/bin/php artisan schedule:run >> /dev/null 2>&1

The 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:run

because Laravel's artisan file is normally one level above public.

Correct:

cd /home/user/public_html && php artisan schedule:run

assuming your project root is public_html.

Common Laravel Cron Mistake: Running index.php

You do not need to execute:

public/index.php

for the Laravel scheduler.

Use Artisan:

php artisan schedule:run

The 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:run

This 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

  • artisan file exists

  • php artisan schedule:run works manually

  • Scheduled task is actually due

  • Application timezone

  • Server timezone

  • .env configuration

  • Cached configuration

  • Database connectivity

  • Storage permissions

  • Laravel logs

  • Cron output logs

Useful Commands

Check PHP:

php -v

Find PHP:

which php

Check project directory:

pwd

Test Laravel:

php artisan

Run scheduler manually:

php artisan schedule:run

View the schedule:

php artisan schedule:list

Clear Laravel cache:

php artisan optimize:clear

Check Laravel logs:

tail -f storage/logs/laravel.log

Recommended Production Cron Setup

A typical production setup may look like:

* * * * * cd /home/username/laravel-app && /usr/bin/php artisan schedule:run >> /dev/null 2>&1

Laravel 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:run

Use 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