Linux flock, how to just lock a file?
To lock the file:
exec 3>filename # open a file handle; this part will always succeed
flock -x 3 # lock the file handle; this part will block
To release the lock:
exec 3>&- # close the file handle
You can also do it the way the flock man page describes:
{
flock -x 3
...other stuff here...
} 3>filename
...in which case the file is automatically closed when the block exits. (A subshell can also be used here, via using ( )
rather than { }
, but this should be a deliberate decision -- as subshells have a performance penalty, and scope variable modifications and other state changes to themselves).
If you're running a new enough version of bash, you don't need to manage file descriptor numbers by hand:
# this requires a very new bash -- 4.2 or so.
exec {lock_fd}>filename # open filename, store FD number in lock_fd
flock -x "$lock_fd" # pass that FD number to flock
exec $lock_fd>&- # later: release the lock
...now, for your function, we're going to need associative arrays and automatic FD allocation (and, to allow the same file to be locked and unlocked from different paths, GNU readlink) -- so this won't work with older bash releases:
declare -A lock_fds=() # store FDs in an associative array
getLock() {
local file=$(readlink -f "$1") # declare locals; canonicalize name
local op=$2
case $op in
LOCK_UN)
[[ ${lock_fds[$file]} ]] || return # if not locked, do nothing
exec ${lock_fds[$file]}>&- # close the FD, releasing the lock
unset lock_fds[$file] # ...and clear the map entry.
;;
LOCK_EX)
[[ ${lock_fds[$file]} ]] && return # if already locked, do nothing
local new_lock_fd # don't leak this variable
exec {new_lock_fd}>"$file" # open the file...
flock -x "$new_lock_fd" # ...lock the fd...
lock_fds[$file]=$new_lock_fd # ...and store the locked FD.
;;
esac
}
If you're on a platform where GNU readlink is unavailable, I'd suggest replacing the readlink -f
call with realpath
from sh-realpath by Michael Kropat (relying only on widely-available readlink functionality, not GNU extensions).
Unable to lock file linux
The flock
command uses flock(2)
to lock the file. As the documentation says
flock()
places advisory locks only; given suitable permissions on a file, a process is free to ignore the use offlock()
and perform I/O on the file.
In general, applications don't check advisory locks. They're intended for use within a specific application to coordinate between multiple processes.
The flock
command is most often used by a single application just to prevent itself from running multiple times concurrently.
flock: when to use the -o (--close) option?
I was just trying to determine this myself! The man page does not provide a clear description:
-o, --close
Close the file descriptor on which the lock is held before executing command. This is useful if command spawns a child process which should not be holding the lock.
My question was... what is the point of having a lock if you're releasing it before the command executes? I found an answer here: https://utcc.utoronto.ca/~cks/space/blog/linux/FlockUsageNotes
It states:
flock -n -o LOCKFILE SHELL-SCRIPT [ARGS ...]
Run this way, the only thing holding the lock is flock itself. When flock exits (for whatever reason), the file descriptor will be closed and the lock released, even if SHELL-SCRIPT is still running.
Does flock lock the file across processes?
On Linux (and other UNIX) systems, flock()
is purely a advisory lock. It will prevent other processes from obtaining a conflicting lock on the same file with flock()
, but it will not prevent the file from being modified or removed.
On Windows systems, flock()
is a mandatory lock, and will prevent modifications to the file.
flock doesn't get released on logout/reboot
Don't remove the file; just let the process holding the file open exit.
(
if [[ -n $LOGFILE ]]; then
exec >>"$LOGFILE" 2>&1
fi
flock -xn 200 || { show_message "$(basename ${0}): cannot acquire lock ${LOCK_FILE}"; exit 3; }
main
) 200>"${LOCK_FILE}"
When main
exists, the subshell that opened $LOCK_FILE
will exit as well, and the lock will be dropped.
If you want to release the lock explicitly, use flock --unlock 200
instead of removing the file.
Related Topics
Best Practices When Running Node.Js With Port 80 (Ubuntu/Linode)
How to Declare 2D Array in Bash
What Is Double Dot(..) and Single Dot(.) in Linux
Using Printf in Assembly Leads to Empty Output When Piping, But Works on the Terminal
Asynchronous Io Io_Submit Latency in Ubuntu Linux
Performing Http Requests With Curl (Using Proxy)
Appending a Line to a File Only If It Does Not Already Exist
Difference Between Clock_Realtime and Clock_Monotonic
How to Automatically Redirect Http to Https on Apache Servers
How to Recursively Find All Files in Current and Subfolders Based on Wildcard Matching
Have Bash Script Answer Interactive Prompts
Get Destination Address of a Received Udp Packet
What Is the Runtime Performance Cost of a Docker Container
What Does $@ Mean in a Shell Script
Use Bluez Stack as a Peripheral (Advertiser)
Make -J 8 G++: Internal Compiler Error: Killed (Program Cc1Plus)