web-dev-qa-db-ja.com

flockに複数のコマンドを渡す

flock -x -w 5 ~/counter.txt 'COUNTER=$(cat ~/counter.txt); echo $((COUNTER + 1)) > ~/counter.txt'

上記の例のように、flockに複数のコマンドを渡すにはどうすればよいですか?

私が理解している限り、flockは異なるフラグ(-xは排他、-wはタイムアウト)、次にファイルをロックし、次にコマンドを実行します。この関数に2つのコマンドを渡す方法がわからない(ロックされたファイルの内容で変数を設定してから、このファイルをインクリメントする)。

ここでの私の目標は、スクリプトがcounter.txtファイルにアクセスしようとするたびにファイルをロックすることにより、ファイルに多少アトミックな増分を作成することです。

12
d-_-b

シェルを明示的に呼び出します。

flock -x -w 5 ~/counter.txt sh -c 'COUNTER=$(cat counter.txt); echo $((COUNTER + 1)) > ~/counter.txt'

変更する変数は、そのシェルインスタンスに対してローカルであることに注意してください。たとえば、COUNTER変数は呼び出し元のスクリプトで更新されません。ファイルから読み込む必要があります(ただし、その間に変更された可能性があります)、またはコマンドの出力として次のようにします。

new_counter=$(flock -x -w 5 ~/counter.txt sh -c 'COUNTER=$(cat counter.txt); echo $((COUNTER + 1)) | tee ~/counter.txt')

または、ファイル記述子を群れにすることができます

exec {counterfd}<~/counter.txt
flock -x -w 5 "$counterfd"
COUNTER=$(cat ~/counter.txt)
COUNTER=$(( COUNTER +1 ))
echo "$COUNTER" >~/counter.txt
exec {counterfd}<&-

これには、サブシェルベースのアプローチとは異なり、カウンター変数を直接使用できるという利点もあります。

4
Richard Maw

flockツールの使い方は少しトリッキーで、manページはかなり短いです。マニュアルページには、ツールを使用する3つの方法があります。

  • flock [options] <file|directory> <command> [command args]
  • flock [options] <file|directory> -c <command>
  • flock [options] <file descriptor number>

この質問の言い方では、flockの3番目の形式を必ず使用します。 flockのmanページのさらに下に行くと、3番目の形式を使用するための正確な構文を示すいくつかの例があります。

#!/bin/bash
(
 flock -n 9 || exit 1
 echo "commands executed under lock..."
 echo "go here..."
) 9>/tmp/mylockfile

#!/bin/bashを追加しました。

この形式のflockを正常に使用しました。

2