Linux flock, как" просто " заблокировать файл?
в Bash я пытаюсь сделать функцию getLock для использования с разными именами блокировки.
function getLock
{
getLock_FILE=""
getLock_OP=""
case "${getLock_OP}" in
"LOCK_UN")
flock -u "${getLock_FILE}"
rm -fr "${getLock_FILE}"
;;
"LOCK_EX")
flock -x "${getLock_FILE}"
esac
}
но стадо говорит flock: bad number: myfilelock
как я могу просто заблокировать файл и выпустить его, когда захочу, без необходимости выполнять команду в стае?
он должен использоваться следующим образом:
getLock myfilelock LOCK_EX
somecommands
........
getLock myfilelock LOCK_UN
1 ответов
заблокировать файл:
exec 3>filename # open a file handle; this part will always succeed
flock -x 3 # lock the file handle; this part will block
чтобы отпустить замок:
exec 3>&- # close the file handle
вы также можете сделать это так, как описывает страница flock man:
{
flock -x 3
...other stuff here...
} 3>filename
...в этом случае файл автоматически закрывается при выходе из блока. (Подсеть также может использоваться здесь, используя ( )
, а не { }
, но это должно быть преднамеренное решение - так как подсхемы имеют штраф за производительность, а изменения переменных области и другие изменения состояния сами.)
если вы используете достаточно новую версию bash, вам не нужно вручную управлять номерами дескрипторов файлов:
# this requires a very new bash -- 4.2 or so.
exec {lock_fd}>filename
flock -x "$lock_fd"
exec $lock_fd>&-
...теперь для вашей функции нам понадобятся ассоциативные массивы и автоматическое выделение FD (и, чтобы один и тот же файл был заблокирован и разблокирован из разных путей, GNU readlink) - так что это не будет работать со старыми выпусками bash:
declare -A lock_fds=() # store FDs in an associative array
getLock() {
local file=$(readlink -f "") # declare locals; canonicalize name
local op=
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
}
если вы находитесь на платформе, где GNU readlink недоступно, я бы предложил заменить readlink -f
вызов с realpath
С sh-realpath Майкла Кропата (полагаясь только на широко доступные функции readlink, а не на расширения GNU).