Przejdź do treści głównej

Poradniki / Pojęcia monitoringu wyjaśnione

What is a cron job? Syntax, examples and common pitfalls

A cron job is a command or script that the cron scheduler runs automatically at times you choose, such as every night at 02:30 or every five minutes. The schedule is one line in a crontab file, and the cron daemon checks those lines once a minute.

How cron runs a job

Cron has two parts. The cron daemon (cron on Debian and Ubuntu, crond on Red Hat based systems) starts at boot and wakes up every minute. A crontab ("cron table") is a plain text file of schedules. Each minute the daemon reads the crontabs, finds the lines whose time matches, and starts those commands.

Every user can have a personal crontab. You edit it with crontab -e and list it with crontab -l, and its jobs run as that user. The system also reads /etc/crontab and the files in /etc/cron.d/. Those files have one extra column, the user name, between the schedule and the command.

A crontab line is a schedule followed by a command:

# minute hour day-of-month month day-of-week  command
30 2 * * *    /usr/local/bin/backup.sh
*/5 * * * *   /usr/bin/python3 /opt/app/sync.py
0 9 * * MON   /home/deploy/bin/weekly-report.sh

The five fields are minute, hour, day of month, month and day of week. A star means every value, a comma makes a list, a dash makes a range and a slash makes a step. So the first line runs at 02:30 every day, the second every five minutes, and the third at 09:00 every Monday. The special characters, the shorthand macros and a table of common schedules are in the cron expression guide, so this page does not repeat them.

People usually schedule work that nobody wants to do by hand:

  • database dumps and file backups
  • deleting old logs, temporary files and expired sessions
  • renewing a TLS certificate or clearing a cache
  • building a sitemap, a data feed or a report
  • importing data from another system on a fixed interval

Where scheduled jobs run

Linux and BSD. Many server distributions include cron by default. Minimal container images often do not, so a job copied from a server may have no scheduler to run it inside a container. On systems that use systemd, a timer unit does the same work with a different file format, and systemctl list-timers shows what is scheduled.

macOS. Cron still works, but Apple's documentation calls it deprecated in favor of launchd. A launchd job is a property list file with a StartCalendarInterval key. Cron jobs do not run while the Mac is asleep or switched off.

Windows. Task Scheduler is the equivalent. It has a graphical console and a command line tool. This command creates a task that runs a script every day at 02:30:

schtasks /create /tn "Nightly backup" /tr "C:\scripts\backup.cmd" /sc daily /st 02:30

Kubernetes. A CronJob object takes the same five-field expression in spec.schedule and creates a Job at each matching time. The timeZone field has been stable since version 1.27, and concurrencyPolicy: Forbid skips a run if the previous one is still going:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: nightly-cleanup
spec:
  schedule: "30 2 * * *"
  timeZone: "Etc/UTC"
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: cleanup
            image: registry.example.com/cleanup:1.0

Kubernetes documents that a CronJob may occasionally create two Jobs or none, so the work inside should be safe to run twice.

Hosting panels and cloud schedulers. Shared hosting control panels have a "Cron Jobs" page, and cloud providers sell managed schedulers. Many accept cron-style expressions, but some add a seconds or year field and some run only in UTC. Read the syntax page of the service before you paste an expression from a Linux crontab.

Pitfalls that make a cron job fail

Most failed cron jobs work fine when you run them by hand. The difference is the way cron starts them.

  1. A minimal environment. Cron sets SHELL=/bin/sh and takes HOME and LOGNAME from the user entry. PATH is short, often only /usr/bin:/bin. A command that lives in /usr/local/bin is "not found". Use absolute paths, or set variables at the top of the crontab:
    SHELL=/bin/bash
    PATH=/usr/local/bin:/usr/bin:/bin
    [email protected]
  2. The wrong working directory. Cron usually starts the job in the user's home directory, not in the folder of the script. Relative paths break. Use absolute paths, or start the command with cd /path &&.
  3. Time zone and clock changes. Cron reads the schedule in the time zone of the machine, and many servers use UTC. According to the Linux crontab manual page, a job set inside the hour that daylight saving time skips is not run, and a job set inside the hour that happens twice runs twice. Other cron implementations can behave differently. Keep servers on UTC, or avoid the hours around 02:00.
  4. Overlapping runs. Cron does not wait for the previous run to finish. A job that sometimes takes seven minutes and runs every five will pile up. Take a lock with flock:
    */5 * * * * flock -n /tmp/sync.lock /usr/local/bin/sync.sh
  5. Lost output. Cron mails anything the job prints to the crontab owner, or to MAILTO if you set it. On many servers no mail system is configured, so the output disappears. Write it to a file you will read:
    0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
  6. A percent sign in the command. In a crontab, % means a newline, so date +%F breaks. Write date +\%F.
  7. A comment on the same line. Comments must be on their own line. A comment after a command becomes part of the command.
  8. A script that is not executable. Run chmod +x on the script, or call it through its interpreter, as in /bin/bash /opt/app/run.sh.

Cron also does not run a job later if the machine was off at the scheduled time. That run is simply skipped.

How to tell whether a job ran

Check three things in order: the crontab is installed, cron started the command, and the command did its work.

crontab -l
grep CRON /var/log/syslog | tail -20
journalctl -u cron --since "2 hours ago"
sudo tail -20 /var/log/cron

The first command shows the installed schedule for your user. The second works on Debian and Ubuntu systems that use rsyslog. The third reads the systemd journal, and the unit is called crond on Red Hat based systems. The fourth is the log file on those Red Hat based systems.

A log line proves only that cron launched the command. It does not show that the command succeeded. Have the script write its own start time, end time and exit code to a log file.

If the job fails under cron but works in your terminal, reproduce cron's environment:

env -i HOME="$HOME" SHELL=/bin/sh PATH=/usr/bin:/bin /bin/sh -c '/usr/local/bin/backup.sh'

When that command fails and your normal shell succeeds, the problem is the environment, usually a missing variable or a command that is not on the short PATH.

Frequently asked questions

What is the difference between cron and crontab?

Cron is the background service that starts jobs. A crontab is the file that lists the schedules. The word is also a command: crontab -e edits your file.

Can a cron job run every second?

No. Cron looks at its schedules once a minute, so one minute is the smallest interval. For shorter intervals, use a program that keeps running and waits between tasks, or a systemd timer.

What is the difference between cron and a systemd timer?

Both start a command on a schedule. Cron is one line per job and works on almost every Unix-like system. A systemd timer needs two unit files, writes its output to the journal, and can run a missed job after downtime when you set Persistent=true.

Does cron run missed jobs after a reboot?

No. If the machine was off at 02:30, the 02:30 run does not happen. Anacron and systemd timers with Persistent=true exist for jobs that must catch up.

How do I stop a cron job?

Run crontab -e and delete the line, or put a # at the start of it. Do not use crontab -r unless you mean it: it deletes your whole crontab without asking.

Build and test a schedule

Five fields are easy to misread, so check a schedule before you rely on it. HostTracker's crontab generator builds an expression from presets, or reads one you paste. It explains the expression in plain English, names the field that is wrong, and lists the next five run times in your time zone or in UTC. It runs in your browser and needs no account. For the full syntax and a table of common schedules, read the cron expression guide.

Sources and further reading

Sprawdź teraz

Uruchom darmowe sprawdzenie na swojej stronie - bez zakładania konta.

Crontab generator

Monitoruj to na stałe

Otrzymasz powiadomienie w chwili awarii: HostTracker sprawdza z ponad 300 lokalizacji i powiadamia e-mailem, SMS-em, przez Slack, Telegram i nie tylko.

Funkcje HostTracker

Więcej w tej sekcji: Pojęcia monitoringu wyjaśnione