Skip to content

Grokem · https://www.grokem.com/data/data-engineering/data-orchestration/cron-flock-scheduled-jobs

  • Intermediate
  • 15 min to complete

0 sec

Before you start

  • A Linux or macOS machine (or server) where you can edit your crontab
  • A script that runs correctly from the command line

cron is the oldest and simplest job scheduler on Unix, and it is still how a great deal of real work gets run. Its simplicity is also why a first attempt often fails silently. This guide covers the entry itself, the reasons jobs "do not run", and how to stop a slow job from being run twice at once.

1. The format

Edit your own crontab with:

bash
crontab -e

Each line has five time fields and then a command:

text
# minute  hour  day-of-month  month  day-of-week  command
  */15    *     *             *      *            /usr/bin/python3 /opt/jobs/report.py
  30      6     *             *      1-5          /opt/jobs/morning.sh
  0       2     1             *      *            /opt/jobs/monthly.sh
  • */15 * * * *: every 15 minutes.
  • 30 6 * * 1-5: 06:30 on Monday to Friday (0 or 7 is Sunday).
  • 0 2 1 * *: 02:00 on the first day of every month.

crontab -l lists what is installed. The time zone is the system's, unless the cron implementation supports setting CRON_TZ, so check which you are in.

2. Why a job works by hand and not in cron

Cron runs jobs in a bare environment, not your login shell. The usual causes:

  • A short PATH. Use absolute paths for the program and for the script (/usr/bin/python3, not python3), and for any files the script opens, or set the working directory first: cd /opt/jobs && ....
  • No profile or virtualenv. Call the virtual environment's Python directly: /opt/jobs/.venv/bin/python.
  • Missing environment variables. Define them at the top of the crontab, or in a file your script reads, rather than assuming your shell's.
  • The % character. In a crontab, an unescaped % is treated as a newline. Escape it as \%, which matters in date +%F style commands.
  • Permissions. The script must be executable (chmod +x) and readable by the user whose crontab it is.

3. Capture the output

By default cron tries to e-mail a job's output to the user, which on most machines goes nowhere. Redirect it to a log yourself:

text
*/15 * * * * /opt/jobs/.venv/bin/python /opt/jobs/report.py >> /var/log/report.log 2>&1

>> appends, and 2>&1 sends error messages to the same place. Without it, a failing job leaves no trace. Rotate the log file (for example with logrotate) so it does not grow without limit.

4. Stop overlapping runs with a lock

If a job takes 20 minutes and runs every 15, the second run starts while the first is still going. Two copies fight over the same files and database rows. A lock prevents that. On Linux, flock takes an exclusive lock on a file, and -n (non-blocking) makes the new run give up immediately if the lock is held:

text
*/15 * * * * flock -n /tmp/report.lock /opt/jobs/.venv/bin/python /opt/jobs/report.py >> /var/log/report.log 2>&1

While the first run holds /tmp/report.lock, the next one exits at once with a non-zero status and the job is not started twice. When the first run ends, or the process dies, the lock is released automatically, so a crash cannot leave the job stuck for good. That is the advantage over a hand-made "lock file" that you create and delete yourself.

5. Make the job safe to run again

Cron will run the job on schedule whether or not the last run worked. Design for that:

  • Be idempotent: running the same job twice for the same period should leave the same result.
  • Take the period as an argument instead of using "now", so you can re-run the previous day after a failure.
  • Exit non-zero on failure, so a wrapper or monitor can see that it failed.
  • Tell someone when it breaks. A job that silently stops running is the hardest failure to notice. Have the job ping a monitoring service when it finishes successfully, and alert if the ping stops arriving.

When to move on

Cron does one thing: start a command at a time. It does not know about dependencies between jobs, retry failures, backfill missed periods or show you a history. When you start needing those, or when you have more than a handful of jobs, a workflow orchestrator pays for its extra complexity. Until then, a clean crontab with locks and logs is hard to beat.

Expected result

The job runs at the times you set, writes its output to a log file, and if one run is still going when the next is due, the new one exits at once instead of running alongside it.

Frequently asked questions

What does the asterisk mean?

It means every value of that field. */15 in the minute field means every 15 minutes.

Is cron enough for data pipelines?

For a few independent jobs, yes. When jobs depend on each other, need retries, backfills and visibility, a workflow orchestrator earns its complexity.

References

From Grokem: https://www.grokem.com/data/data-engineering/data-orchestration/cron-flock-scheduled-jobs

Lesson 7 of 7 in Data pipelines you can trust

How did this strike you?

Be the first to react – it is anonymous.

Community

Questions about this?

Ask in Questions and help and get help from other readers.

Ask a questionBrowse Questions and help

Comments (2)

  • Kwame A.

    What happens to the lock if the server reboots in the middle of the job?

    • Grokem Editorial

      The lock belongs to the running process, not to the file. When the process ends for any reason, including a reboot or a crash, the system releases it, so the next scheduled run starts normally. The job itself should still be safe to run again.

Choose what we may use. You can change this at any time with “Privacy choices” at the foot of every page. Details are in the Cookie policy and the Privacy policy.

Strictly necessary

Remembers your theme, the lessons you marked as done and this choice. It stays on your device, tracks nothing and cannot be switched off.

Always on
What exactly is collected, and why

Grokem’s own counts

Collects
The pages you open and how long you stay, how far you scroll, where you came from, your device type, browser, screen size, language and time zone. Your IP address is turned into a code that changes every day; it is never stored as it is.
Why
To see how long lessons are read and where readers leave. Not shared with anyone.
Stored
A random visitor ID, a visit ID and the time of your last page view in your browser’s storage (gr_vid, gr_sid, gr_last). No name or email is attached.