In this lesson, you will learn how to prevent long-running cron jobs from overlapping by implementing a simple, file-based locking mechanism.
When you schedule a task via cron, it is common to set an interval shorter than the job's total runtime if you assume the system is idle. However, if a process hangs or a data set grows unexpectedly, multiple instances of the same script can run simultaneously, leading to race conditions, database corruption, or resource exhaustion.
The Lockfile Pattern
A "lockfile" acts as a semaphore. Before the script performs its main work, it checks for the existence of a specific file. If the file exists, the script assumes another instance is running and exits immediately. If it doesn't exist, the script creates the file, completes its task, and then removes (deletes) the file upon completion.
We typically use the flock utility, which is built for this exact purpose. It handles the atomic creation of the lock and ensures that even if the script crashes, the lock can be released by the system.
Practical Implementation
Consider a script that processes heavy logs. You can wrap the execution in a flock command directly within your crontab or inside the script itself:
#!/bin/bash
# Process-locked task
LOCKFILE=/tmp/my_task.lock
# Open file descriptor 200 for the lockfile
exec 200>$LOCKFILE
# Try to acquire an exclusive lock (non-blocking)
flock -n 200 || { echo "Task is already running"; exit 1; }
# Perform the heavy lifting
./heavy_process.sh
# Lock is automatically released when the script exits
By using flock -n (non-blocking), the script will immediately exit with a failure code if it detects the lockfile held by another process. This prevents the "stacking" effect that occurs when a job takes longer than its scheduled frequency. When the script terminates, the file descriptor closes and the lock is relinquished, allowing the next scheduled run to proceed.
Key Takeaway: Use flock to create an atomic, file-based sentinel that prevents concurrent execution of your automated tasks.