Skip to main content

PHP in Cron: How CLI Differs from FPM in Practice

PHP · 29.09.2026

How PHP CLI Differs from PHP-FPM for Cron Jobs

PHP-FPM handles HTTP requests through Nginx and runs as a pool of workers sharing one php.ini with limits tuned for web traffic. PHP CLI is a separate binary, /usr/bin/php8.3, launched from the command line or from crontab, and it reads its own config, usually from /etc/php/8.3/cli/php.ini. The values of memory_limit, max_execution_time, and error_reporting can differ between CLI and FPM, which is a common reason a script works fine in the browser but the same script fails on schedule, or the other way around.

The second difference is the environment. A cron process has none of the PATH, HOME, and locale variables an interactive shell has, and no default working directory: it always starts from the home directory of the user that owns the cron job.

How to Write a Cron Job Correctly

A crontab rule should specify the full path to the PHP binary, the full path to the script, and the working directory if the script uses relative file paths.

*/5 * * * * cd /var/www/app && /usr/bin/php8.3 artisan schedule:run >> /var/log/app/cron.log 2>&1

The && operator guarantees that php only runs after successfully changing into the directory, and 2>&1 redirects errors into the same log file as regular output. Without this, fatal PHP errors disappear silently: cron mails them to a local mailbox nobody reads.

A Separate php.ini for CLI

You can check which config CLI actually uses with a single command — it shows the real file path instead of a guess.

php --ini
php -i | grep memory_limit

If the server has several PHP versions installed, as described in the article on running multiple PHP versions on one server, always specify the version explicitly in crontab: /usr/bin/php8.3, not just php — otherwise the job can suddenly run under a different version after an alternatives update.

Memory, Timeouts, and Working Directory: Common Pitfalls

ParameterWeb (FPM)Cron (CLI)
memory_limit128Moften unlimited (-1)
max_execution_time30 seconds0, no limit
working directorysite rootuser home directory
error_logPHP-FPM logstderr, unless set explicitly

The values in this table are set in different sections of php.ini: [PHP] affects both modes, while the cli/conf.d block affects only CLI. Memory and upload management are covered in detail in the article on memory_limit and upload_max_filesize.

Logging Cron Job Output

  • Always redirect stdout and stderr to a dedicated log file instead of relying on cron's mail.
  • Set display_errors = Off and log_errors = On in cli/php.ini — printing errors to the console breaks the format if the script outputs JSON or CSV.
  • Configure log rotation for the cron log through logrotate, otherwise the file grows to gigabytes within a month.
  • Start investigating a failed job from error_log, not from guesses — the approach is covered in the article on PHP logs and diagnosing fatal errors.
  • Prepend date and hostname to every log line for each job — on a cluster of several servers, otherwise there is no way to tell which one wrote it.

Summary: Checklist for PHP Jobs in Cron

  • Crontab specifies the full path to the correct PHP version binary and the working directory via cd.
  • Command output is redirected to a log file with rotation configured through logrotate.
  • memory_limit and max_execution_time were checked in cli/php.ini, not in the FPM config.
  • display_errors is off, log_errors is on, and errors go to a file instead of root's mailbox.
  • The job was tested manually as the same user account that cron uses to run it.
← Back to Knowledge Base Ask Support