Linux flock, comment "juste" verrouiller un fichier?

dans Bash, j'essaye de faire un getLock de fonction pour être utilisé avec des noms de serrures différents.

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
}

mais flock dit flock: bad number: myfilelock

Comment puis-je verrouiller un fichier, et de le libérer quand je veux, sans avoir à exécuter une commande dans le troupeau?

C'est pour être utilisée comme ceci:

getLock myfilelock LOCK_EX
somecommands
........
getLock myfilelock LOCK_UN
13
demandé sur JorgeeFG 2014-06-24 17:32:16

1 réponses

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ébloquer la serrure:

exec 3>&-       # close the file handle

vous pouvez aussi le faire de la façon décrite dans la page de manuel flock:

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

... auquel cas le dossier est automatiquement fermé lorsque le bloc sort. (Un subshell peut aussi être utilisé ici, via ( ) plutôt que { }, mais cela devrait être une décision délibérée , car les cellules ont une pénalité de performance, et des modifications des variables de champ d'application et d'autres changements d'état. m'.)


si vous utilisez une nouvelle version de bash, vous n'avez pas besoin de gérer les numéros de descripteur de fichier à la main:

# 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 automatique de FD (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 versions plus anciennes de 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
}

si vous êtes sur une plate-forme où GNU readlink est pas disponible, je vous suggère de remplacer le readlink -f appel realpathsh-realpath par Michael Kropat (s'appuyant uniquement sur la fonctionnalité readlink largement disponible, et non sur les extensions GNU).

29
répondu Charles Duffy 2017-06-20 12:45:42