Cron Jobs

By the end of this lesson you'll be able to read and write cron expressions, schedule a PHP CLI script to run automatically, log its output, and stop two runs from colliding — the toolkit behind every nightly backup and email digest.

Learn Python, JavaScript, Java and more with free interactive lessons, real projects and AI-powered help. Beginner-friendly.

Part of the free Php course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

1️⃣ Cron Syntax: The Five Fields

A cron job is a command your server runs automatically on a schedule. That schedule is written as five space-separated fields followed by the command: minute hour day-of-month month day-of-week command . An asterisk ( * ) means "every value", */5 means "every 5th", a dash like 1-5 is a range , and a comma like 1,15 is a list . Learn to read these six lines and you can express almost any schedule.

Cron itself prints nothing — it just launches the command at the right moment. The fields only decide when . A common gotcha: the day-of-month and day-of-week fields are OR-ed together, so 0 0 13 * 5 runs on the 13th and on every Friday, not only Friday the 13th.

2️⃣ Installing a Job with crontab -e

Each user has their own crontab (cron table). You edit it with crontab -e , which opens an editor; the moment you save, the schedule is live. The command in a cron line is run by a bare shell, so you give the full path to PHP and the full path to your script : /usr/bin/php /var/www/app/backup.php . Cron throws away your script's output unless you capture it — so always redirect it to a log file with file.log 2 &1 (append stdout, and send errors to the same place).

3️⃣ The PHP CLI Script Cron Runs

The script cron launches is ordinary PHP, but run from the command line rather than a browser. That mode is called the CLI SAPI (Server API), and php_sapi_name() returns "cli" there. There is no web page, so everything you echo goes to stdout — which the cron line redirects into your log file. Finish with a clear exit code : exit(0) for success, anything else for failure.

Because each line is timestamped with date('Y-m-d H:i:s') , the log tells you not just that the job ran but when — the first thing you'll want when something breaks at 2 AM.

4️⃣ Preventing Overlap with flock

What happens if a job scheduled */5 * * * * sometimes takes seven minutes? Cron starts the next copy on top of the first, and now two runs fight over the same data. A file lock stops this: the first run grabs an exclusive lock; any later run that can't grab it simply exits. You can do this in the cron line with the flock command (shown in section 2) or inside PHP with the flock() function below.

5️⃣ Your Turn: Write a Cron Line

Now you write the schedule. The line below is almost complete — fill in each ___ using the field order and the 👉 hints, then check it against the Output panel.

One more — this time the PHP script. Cron will redirect its output to a log, so give every line a timestamp . Fill in the blanks and run it.

6️⃣ Alternatives: systemd Timers & the Laravel Scheduler

Plain crontab is everywhere, but two alternatives solve its weak spots. systemd timers pair a .timer unit (when) with a .service unit (what), giving you centralised logging via journalctl -u myjob , dependencies, and easy enable / disable . The Laravel scheduler flips the model: you define all schedules in PHP and add a single cron line that runs php artisan schedule:run every minute.

📋 Quick Reference — Cron Fields & Commands

No code is filled in this time — just a brief and an outline. Write it yourself, run it on onecompiler.com/php or your own machine, then check your result against the expected output in the comments. This combines the lock and the timestamped log into one real cron-ready script.

Practice quiz

What is the correct order of the five cron fields?

  • hour, minute, day, month, year
  • day-of-week, month, day, hour, minute
  • minute, hour, day-of-month, month, day-of-week
  • second, minute, hour, day, month

Answer: minute, hour, day-of-month, month, day-of-week. Read left to right: minute (0-59), hour (0-23), day-of-month (1-31), month (1-12), day-of-week (0-6), then the command.

What does the cron expression '0 9 * * 1-5' mean?

  • 09:00, Monday to Friday
  • Every 9 minutes on weekends
  • 9 PM on the 1st to 5th of the month
  • Midnight every 9 days

Answer: 09:00, Monday to Friday. Minute 0, hour 9, any day-of-month, any month, day-of-week 1-5 (Mon-Fri) — so 9 AM on weekdays.

What does the token '*/5' mean in the minute field?

  • Exactly minute 5
  • Minutes 1 through 5
  • Five times total
  • Every 5th minute

Answer: Every 5th minute. * means 'every', */5 means 'every 5th', a-b is a range, and a,b is a list.

Why must you use absolute paths in a crontab command?

  • Cron only accepts uppercase paths
  • Cron runs with a bare environment, so 'php' or './script.php' may not resolve
  • Relative paths are a syntax error
  • Absolute paths run faster

Answer: Cron runs with a bare environment, so 'php' or './script.php' may not resolve. Cron uses a minimal PATH and a different working directory, so use /usr/bin/php /var/www/app/script.php — full paths to both.

How do you capture both normal output and errors from a cron job to a log file?

  • >> file.log 2>&1
  • | file.log
  • > file.log only
  • 2>file.log only

Answer: >> file.log 2>&1. >> appends stdout to the log and 2>&1 sends stderr to the same place. Without this, a failing job is silent and undebuggable.

Which command opens your personal crontab in an editor?

  • crontab -l
  • crontab -r
  • crontab -e
  • cron --edit

Answer: crontab -e. crontab -e edits (and installs on save), crontab -l lists, and crontab -r removes ALL of the user's jobs.

How do you stop two copies of a cron job from running at the same time?

  • Schedule it less often and hope
  • Wrap it in flock with a lock file (or call flock() in PHP)
  • Run it as root
  • Add MAILTO to the crontab

Answer: Wrap it in flock with a lock file (or call flock() in PHP). flock -n /tmp/job.lock (or PHP's flock($handle, LOCK_EX | LOCK_NB)) makes a second run exit instead of overlapping.

In a PHP CLI script, what does php_sapi_name() return when run from cron?

  • 'fpm'
  • 'cron'
  • 'apache'
  • 'cli'

Answer: 'cli'. From the command line (and cron) PHP runs as the CLI SAPI, so php_sapi_name() returns 'cli'.

Which exit code signals a successful cron run?

  • exit(1)
  • exit(0)
  • exit(200)
  • exit(-1)

Answer: exit(0). exit(0) means success; any non-zero code is recorded by cron as a failed run.

Which is a modern alternative to plain crontab on a single server?

  • An infinite PHP while-loop
  • A browser refresh tag
  • systemd timers (a .timer plus a .service unit)
  • A Composer script

Answer: systemd timers (a .timer plus a .service unit). systemd timers give logging via journalctl, dependencies, and easy enable/disable; the Laravel scheduler keeps timing logic in PHP with one cron line.