NightFox

NightFox

PHP CLI Scripts, Cron Jobs, and Automation

PHP is useful beyond web requests. CLI scripts can import data, process queues, run maintenance, synchronize APIs, and perform repeatable operational tasks.

A Safe CLI Entry Point

#!/usr/bin/env php
<?php
declare(strict_types=1);

require dirname(__DIR__) . '/vendor/autoload.php';

if (PHP_SAPI !== 'cli') {
    fwrite(STDERR, "This command must run from the CLI.\n");
    exit(1);
}

$options = getopt('', ['file:', 'dry-run']);
$filename = $options['file'] ?? null;
$dryRun = array_key_exists('dry-run', $options);

if (!is_string($filename) || !is_readable($filename)) {
    fwrite(STDERR, "Usage: import.php --file=/path/data.csv [--dry-run]\n");
    exit(2);
}

fwrite(STDOUT, $dryRun ? "Dry-run mode enabled.\n" : "Import starting.\n");

Exit Codes Matter

CodeMeaning
0Successful completion
1General runtime failure
2Usage or validation error

Schedulers and monitoring systems use exit codes to determine whether a job succeeded.

Prevent Overlapping Runs

<?php
declare(strict_types=1);

$lock = fopen(sys_get_temp_dir() . '/customer-sync.lock', 'c');

if ($lock === false || !flock($lock, LOCK_EX | LOCK_NB)) {
    fwrite(STDERR, "Another sync is already running.\n");
    exit(1);
}

try {
    // Run the synchronization.
} finally {
    flock($lock, LOCK_UN);
    fclose($lock);
}

Design for Retries

  • Make operations idempotent whenever possible.
  • Checkpoint progress for large imports.
  • Use unique external IDs to prevent duplicates.
  • Set timeouts on network calls.
  • Retry transient failures with backoff and a limit.
  • Send permanent failures to a review queue.

Cron Example

*/5 * * * * /usr/bin/php /var/www/app/bin/process-queue.php \
  >> /var/log/app/process-queue.log 2>&1

Use absolute paths and a predictable environment. Cron often has a smaller PATH and different environment variables than an interactive shell.

Long-Running Workers

Release database transactions promptly, reconnect after failures, cap memory growth, and restart workers after a reasonable number of jobs. Deployments should signal or replace old workers so they do not continue running outdated code.

Last Modified: July 17, 2026, 11:57 pm