Linux flock, how to "just" lock a file?

In Bash, I'm trying to use the getLock function to use with different lock names.

function getLock { getLock_FILE="${1}" getLock_OP="${2}" case "${getLock_OP}" in "LOCK_UN") flock -u "${getLock_FILE}" rm -fr "${getLock_FILE}" ;; "LOCK_EX") flock -x "${getLock_FILE}" esac } 

But the herd says flock: bad number: myfilelock

How can I just lock the file and free it when I want, without having to execute the command in the pack?

It should be used as follows:

 getLock myfilelock LOCK_EX somecommands ........ getLock myfilelock LOCK_UN 
+6
source share
1 answer

To lock a 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 a lock:

 exec 3>&- # close the file handle 

You can also do this as the herd page describes:

 { flock -x 3 ...other stuff here... } 3>filename 

... and in this case, the file is automatically closed when you exit the block. (Here you can also use a subshell using ( ) rather than { } , but this should be a deliberate solution - since subshells have performance limitations and modifications to region variables and other state changes for themselves).


If you are using a sufficiently new version of bash, you do not need to manually manage the file descriptor numbers:

 # this requires a very new bash -- 4.2 or so. exec {lock_fd}>filename flock -x "$lock_fd" exec $lock_fd>&- 

... now for your function we need associative arrays and automatic FD distribution (and so that the same file is locked and unlocked from different paths, GNU readlink) t with older versions of bash:

 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 are on a platform where GNU readlink is not available, I would suggest replacing the readlink -f call with the realpath from sh-realpath from Michael Kropat (relying only on the widely available readlink function, not the GNU extensions).

+23
source

Source: https://habr.com/ru/post/971288/


All Articles