Prevent Concurrent Cron Jobs Using `flock`


flock
is a utility in Unix-like operating systems (like Linux) used for advisory file locking. Its primary purpose is to prevent multiple instances of a script or process from concurrently accessing and potentially corrupting a shared file or resource.
Here's a breakdown of what flock
is and why it's important:
The Problem: Race Conditions and Data Corruption
Imagine you have a shell script that updates a log file or a configuration file. If this script is run by multiple processes simultaneously (e.g., from different cron jobs, or by multiple users), you could run into a "race condition":
- Process A reads the file.
- Process B also reads the file (before A has finished writing).
- Process A modifies its copy of the data and writes it back to the file.
- Process B (still working with the old data) modifies its copy and writes it back, potentially overwriting Process A's changes or causing inconsistent data.
This can lead to data loss, corruption, or unpredictable behavior.
How flock
Solves This: Advisory Locks
flock
addresses this by implementing advisory locks. Here's how it works:
- Lock File: You designate a specific file (often an empty "lock file") that all cooperating processes will attempt to lock before proceeding.
- Acquire Lock: When a script starts, it attempts to acquire a lock on this designated file using
flock
. - Two Types of Locks:
- Exclusive Lock (
-x
or default): Only one process can hold an exclusive lock on a file at a time. If another process tries to acquire an exclusive lock while one is held, it will either wait (default behavior) or fail immediately (-n
, non-blocking). This is typically used for write operations. - Shared Lock (
-s
): Multiple processes can hold a shared lock on a file simultaneously. However, no process can hold an exclusive lock while a shared lock is active, and vice versa. This is typically used for read operations where multiple readers are fine, but a writer needs exclusive access.
- Exclusive Lock (
- Execute Command: Once the lock is acquired, the script proceeds with its critical operations (e.g., modifying the shared file).
- Release Lock: When the script finishes, the lock is automatically released when the file descriptor associated with the lock file is closed (which happens when the script exits). You can also explicitly release a lock with
-u
.
Key Characteristics and Use Cases
- Advisory Nature: It's important to understand that
flock
provides advisory locking. This means the operating system doesn't force processes to obey the lock. Forflock
to be effective, all processes that access the shared resource must explicitly useflock
to acquire a lock before accessing the resource. If a process ignoresflock
, it can still read or write the file, potentially leading to corruption. Preventing Concurrent Cron Jobs: A very common use case is to ensure that a cron job doesn't run on top of itself if a previous instance is still running.
#!/bin/bash LOCKFILE="/var/lock/my_script.lock" # Try to acquire an exclusive, non-blocking lock. # If the lock is already held, exit immediately (do not run). exec 200>$LOCKFILE flock -n 200 || exit 1 # If we reached here, the lock was acquired. echo "Script started at $(date)" >> /var/log/my_script.log # Simulate some work that takes time sleep 30 echo "Script finished at $(date)" >> /var/log/my_script.log # The lock is automatically released when the script exits, # because file descriptor 200 is closed.
- Synchronization: It can synchronize access to any shared resource (not just files), as long as all participating processes agree on a common "lock file" to manage access.
- File Descriptors:
flock
can operate on a file path directly or, more commonly, on an open file descriptor (like in the example above, whereexec 200>$LOCKFILE
opens the lock file on file descriptor 200). Operating on a file descriptor is often preferred because the lock is tied to the descriptor and automatically released when the descriptor is closed (e.g., when the script exits), even if the script crashes.
In summary, flock
is a fundamental tool for managing concurrent access to shared resources in shell scripting, providing a cooperative mechanism to maintain data integrity and system stability.
Pro-tip
Thanks for making it this far ๐. Systemd timer is encouraged over cron job. If a timer is still running when the next scheduled trigger comes up, it will not start a second instance. Therefore flock
is not needed here.
Subscribe to my newsletter
Read articles from Hong directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Hong
Hong
I am a developer from Malaysia. I work with PHP most of the time, recently I fell in love with Go. When I am not working, I will be ballroom dancing :-)