Bashでは、関数getLockをさまざまなロック名で使用できるようにしています。
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
}
しかし、群れはflock: bad number: myfilelock
Flockでコマンドを実行せずに、ファイルをロックし、必要なときに解放するにはどうすればよいですか?
次のように使用します。
getLock myfilelock LOCK_EX
somecommands
........
getLock myfilelock LOCK_UN
ファイルをロックするには:
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 "$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
}
GNU readlinkが利用できないプラットフォームを使用している場合、readlink -f
呼び出しをrealpath
から sh-realpath by Michael Kropat (広く利用可能なreadlink機能のみに依存し、GNU拡張機能)には依存しません)。