Dans Bash, j'essaie de créer une fonction getLock à utiliser avec différents noms de verrous.
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
}
Mais le troupeau dit flock: bad number: myfilelock
Comment puis-je simplement verrouiller un fichier et le libérer quand je veux, sans avoir à exécuter une commande dans le troupeau?
Il doit être utilisé comme ceci:
getLock myfilelock LOCK_EX
somecommands
........
getLock myfilelock LOCK_UN
Pour verrouiller le fichier:
exec 3>filename # open a file handle; this part will always succeed
flock -x 3 # lock the file handle; this part will block
Pour déverrouiller:
exec 3>&- # close the file handle
Vous pouvez également le faire comme le décrit la page de manuel flock:
{
flock -x 3
...other stuff here...
} 3>filename
... auquel cas le fichier se ferme automatiquement à la sortie du bloc. (Un sous-shell peut également être utilisé ici, en utilisant ( )
plutôt que { }
, mais cela devrait être une décision délibérée - car les sous-coquilles ont une dégradation des performances et des modifications de variables d'étendue et d'autres changements d'état).
Si vous utilisez une nouvelle version de bash, vous n'avez pas besoin de gérer manuellement les numéros de descripteurs de fichiers:
# this requires a very new bash -- 4.2 or so.
exec {lock_fd}>filename
flock -x "$lock_fd"
exec $lock_fd>&-
... maintenant, pour votre fonction, nous allons avoir besoin de tableaux associatifs et d'allocation FD automatique (et, pour permettre au même fichier d'être verrouillé et déverrouillé à partir de chemins différents, GNU readlink) - donc cela ne fonctionnera pas avec les anciennes versions de 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
}
Si vous êtes sur une plateforme où GNU readlink n'est pas disponible, je vous suggère de remplacer le readlink -f
appeler avec realpath
de sh-realpath par Michael Kropat (en se basant uniquement sur la fonctionnalité de lien de lecture largement disponible, pas GNU).