Linux Flock, How to "Just" Lock a File

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 of flock() 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



Leave a reply



Submit