bashのファイルでアトミック書き込み操作を実行する


13

バッシュを通過した後のドキュメントこの質問とこの私には、それはまだはっきりしていない1は、どのように私はbashで、ファイルへのアトミック書き込み(追記)の操作を行うことができます。複数のインスタンスで実行されるスクリプトがあり、ある時点でデータをファイルに書き込む必要があります。

echo "$RESULT" >> `pwd`/$TEMP_DIR/$OUT_FILE

同時に実行されているすべてのスクリプトからそのファイルへのすべての書き込み操作をアトミックにする(どのようにして、あるインスタンスのデータが別のインスタンスのデータと重複しないようにする)ことができますか?


1
参考までに必要ありません`pwd`。ドット(.)のみを使用できます。また、変数が含まれているため、ファイル名全体を引用する必要があります
ワイルドカード

1
また、FIFO使用する可能性を調べることもできます。
ワイルドカード

@Wildcardありがとう。pwd以前のスクリプトで、現在の作業ディレクトリについてユーザーに通知し、ログファイルにエントリを書き込むために使用していました。今FIFOを見ています。
セビ

1
実際、このまさにサイトでFIFOのより良い紹介があります。数分前に提供したリンクは、POSIXの仕様でmkfifoあり、正確な入門レベルではありません。
ワイルドカード

FIFOであろうとファイルであろうと、2つのインスタンスが同時に書き込みを行い、互いの出力を文字化けするリスクがあります。
クラック

回答:


10

flockman(http://linux.die.net/man/1/flock)の例のように使用する必要があるようです

(
flock -x 200

# Put here your commands that must do some writes atomically

) 200>/var/lock/mylockfile 

そして、アトミックでなければならないすべてのコマンドを()に入れます。


書き込み操作はアトミックになります(flock -s 200#アトミックにいくつかの書き込みを行う必要があるコマンドをここに入力します)または、逆に、ロックは/ var / lock / mylockfileに対してのみ相対的ですか?
セビ

1
スクリプトは/ var / lock / mylockfileをロックしますが、スクリプトの1つのインスタンスのみが書き込みロックを取得できます。他のインスタンスは/var/lock/mylockfile、ロックが使用可能になるまで待機します。
セルゲイキュレンコフ16

-sは共有ロックです-読み取りに適しています。書き込みロックには-x / -eを使用する必要があります。リンクしたマニュアルページにあります。
エヴァン・ベン

このコードのどの時点でロック解除が発生しますか?/var/lock/mylockfile呼び出したプロセスによって何かが書き込まれるとすぐにflock -x
クリスストライチンスキー

@ChrisStryczynskiこの例(flock -x 200; date; sleep 10; date;) 200>/var/lock/mylockfileを2つのシェルで実行し、()のすべてのコマンド(サブシェル内)が実行された後にのみロック解除が発生することを確認できます
Sergey Kurenkov

4

flock操作を連動させる方法の1つです。このユーティリティはutil-linuxツールセットの一部であり、Linuxでのみ使用可能です。幅広いプラットフォームで利用可能なその他のsetlockユーティリティは、daemontoolsパッケージのDaniel J. Bernsteinのユーティリティに基づいています。

  • setlock daemontoolsから
  • setlock Bruce Guenterのdaemontools-encoreより
  • s6-setlock ローラン・ベルコットのs6から
  • chpst Gerrit Papeのrunitから
  • runlock ウェインマーシャルのパープから
  • setlock 私の新しいツールセットから

これらのツールは、M。Kurenkovの回答(flock採用することはできますが、その回答には含まれていません)で使用されているパラダイムとは少し異なります。setlockプログラムを呼び出して、インターロックする必要のあるコマンドにロードチェーンしますsetlockそれ自体がロックファイルを開いてロックし、そのプロセスでファイル記述子を開いたままにします。ロックは、そのプロセスが続く限り持続します(開いているファイル記述子を見つけて閉じることによって明示的にロックを解放するために連鎖された後続のコマンドを除く)。

質問の場合、シェルの組み込みコマンドの代わりに外部 echoを呼び出すことに注意して、出力行を生成するコマンドをインターロックする必要がありますecho

setlock mylockfile echo "$ RESULT" >> ./$TEMP_DIR/$OUT_FILE

この場合、出力ファイルを追加モードで開くことを連動させる必要はありません。ある場合は、ロック内でそのファイルを開く必要があります。そのため、fdredir/ などのプログラムを使用する必要がありますredirfd

setlock mylockfile fdredir --append 1 "./$TEMP_DIR/$OUT_FILE" echo "$ RESULT"
必要に応じてシェル関数に変換できます:

outfile(){setlock mylockfile fdredir --append 1 "./$TEMP_DIR/$OUT_FILE" "$ @"; } 
[…]
outfile echo "$ RESULT"
または、シェル構文に固執し、インターロックの下で実行されている2番目のシェルによって解釈されるようにします。シェル変数が環境変数としてエクスポートされない場合、いくつかの重要な引用が必要です。

setlock mylockfile sh -c 'echo' "$ RESULT" '>> "./'$TEMP_DIR'/'$OUT_FILE'" '

もちろん、これは出力ファイルへの書き込み以外のものに一般化されます:

setlock mylockfile sh -c '…インターロック; もの… '

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.