Run scheduled PHP scripts with cron
Schedule PHP CLI scripts, account for permissions and php.ini differences, and use Laravel scheduling from one cron entry.
A common way to schedule PHP work is to write a CLI script and invoke it from system cron. Laravel can centralize many schedules behind one cron entry. Symfony's Scheduler component uses a different worker-based execution model; it should not be treated as the same integration.
1. Write the script
This sketch assumes your application supplies getPendingUsers() and configures mail delivery:
<?php
// /opt/jobs/send_reminders.php
$users = getPendingUsers();
foreach ($users as $user) {
mail($user['email'], 'Reminder', "Hello, {$user['name']}!");
}
echo date('c') . " processed " . count($users) . " reminders\n";
mail() returning true means the message was accepted for delivery, not that it reached the recipient. Check its return value and record delivery outcomes through your mail system; this loop alone does not establish successful delivery.
2. Set permissions
The task account needs permission to read the script and access its dependencies. An executable bit is needed only if you invoke the script directly:
chmod +x /opt/jobs/send_reminders.php
3. Add a crontab entry
# Run hourly.
0 * * * * /usr/bin/php /opt/jobs/send_reminders.php >> /var/log/reminders.log 2>&1
Ensure the task account can write the log. Check the actual CLI path with command -v php rather than assuming it is /usr/bin/php.
Cron has a limited environment. Use explicit paths, load required configuration deliberately, and record task start, finish, and exit status. When collecting the log with DataKit, run a test through PHP CLI and check that the task name, failure details, and completion record arrive.
CLI and PHP-FPM can load different php.ini files and extensions. Check the CLI environment with php --ini and php -m.
Invoke a script through its shebang
Place the interpreter path before the PHP opening tag:
#!/usr/bin/php
<?php
// Task implementation.
With execute permission, cron can call the script directly:
0 * * * * /opt/jobs/send_reminders.php >> /var/log/reminders.log 2>&1
4. Centralize Laravel schedules
In current Laravel application layouts, schedules can be defined in routes/console.php; older layouts commonly use the console kernel. For example:
use Illuminate\Support\Facades\Schedule;
Schedule::command('emails:send')->hourly();
Schedule::job(new GenerateReport)->dailyAt('02:30');
Import your application's GenerateReport class and define the command and job. A single cron entry evaluates the schedule:
* * * * * cd /var/www/app && /usr/bin/php artisan schedule:run >> /dev/null 2>&1
That entry discards console output, so configure task output or application logging separately if you need it for diagnosis. Keeping schedule definitions in source control makes changes deployable alongside the code.
FAQ
Why does the script work in a browser but fail under cron?
Compare CLI and FPM configuration, extensions, environment variables, working directories, and permissions. Use absolute paths and test as the actual scheduled-task account.
Will a long-running CLI task time out?
PHP CLI defaults max_execution_time to zero, but configuration, set_time_limit(), the process supervisor, or an external timeout can impose limits. Long-running work should support safe retries or checkpoints.
How do I choose among installed PHP versions?
Use the intended binary's full path, such as /usr/bin/php8.2 /opt/jobs/task.php.
References: Laravel scheduling, PHP runtime configuration, PHP mail.
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan