web-dev-qa-db-ja.com

多くのプロセスからログファイルへの同時書き込み

MacOSのターミナルのopenコマンドまたはWindowのターミナルのstartを模倣する場合、 this answer のコメントは、~/.xsession-errorsにstdoutとstderrを追加することを提案します。(bash):

alias open='&>>~/.xsession-errors xdg-open'

これで私が予見する問題は競合状態です。 lsof ~/.xsession-errorsは、22プロセスが書き込み用にファイルを開いていることを示しています。

2つのプロセスが~/.xsession-errorsの同じオフセットに書き込むのを防ぐにはどうすればよいですか?

6
Tom Hale

ファイルが追加モードで開かれると、OSはすべての書き込みが最後に行われることを保証します。したがって、あるライターからのデータが別のライターからのデータを上書きすることはありません。

これは、ファイルが追加モードで、つまりシェルで>>を使用して開かれた場合にのみ適用されます。ファイルの作成者が>でファイルを開いた場合、その保証は適用されず、次のようなシーケンスになる可能性があります。

  • プロセス1:>out;現在位置0
  • プロセス2:>>out;現在位置0
  • プロセス1:helloを書き込みます。現在、位置6にあります
  • プロセス2:worldを書き込みます。これは位置6に書き込まれ、プロセス2は位置12にあります。
  • プロセス1:oopsを書き込みます。これは、プロセス1のファイル位置が変更されていないため、位置6に書き込まれます。

Debianでは(2001年以降)、ファイル.xsession-errorsは `/ etc/X11/Xsessionによって作成され、追加モードで開かれるため、すべて正常です。

 exec >>"$ERRFILE" 2>&1

~/.xsession-errorsにログを記録するすべてのディストリビューションがそうであるかどうかはわかりません。

誰もが追加モードでファイルを開いている限り、すべての出力が存在します。ただし、出力は断片化される場合があります。実際には、通常のファイルへの十分小さい書き込みはアトミックです。 512B未満のものはどこでも十分小さいはずです。Linuxではそれ以上の保証ができると思います¹。そのため、ライターがラインバッファリングされた出力を使用し、ラインが過度に長くないと想定すると、複数の同時ライターがある場合でも、各ログ行はそのまま表示されます。

¹ POSIXはパイプ以外は何も保証しないことに注意してください。

_>>_を POSIXシェルで使用すると、ファイルが_O_APPEND_ で開かれることが保証されます。

The Open Group Base Specifications Issue 7 の状態:

ファイルステータスフラグの_O_APPEND_フラグが設定されている場合、ファイルオフセットは各書き込みの前にファイルの最後に設定され、ファイルオフセットの変更と書き込み操作の間にファイル変更操作が発生してはなりません。

POSIXは、単一の write(2) 呼び出しで要求して書き込むことができる最小バイト数を定義します( _SSIZE_MAX_ = 32,767 )。戻り値は実際に書き込まれたバイト数です(保証されたアトミック)。

しかしながら

すべてのファイルシステムが準拠しているわけではありません。 複数のプロセスからのファイルへの追加 は言う:

注意点は、すべてのファイルシステムがPOSIX互換であるわけではないということです。 2つの有名な例はNFSとHadoop分散ファイルシステム(HDFS)です。これらのネットワーク化されたファイルシステムでは、追加がシミュレートされ、競合状態の影響を受けます。

誰もがニースを演じるわけではない

_O_APPEND_を使用して開くことはできますが、ファイルに書き込む他のプロセスは開かないことがあります。特定のファイルを確認できます。

_lsof +fg <file>
_

心配なことに、_lsof +fg ~/.xsession-errors_を実行すると、noAP(追加)フラグが表示され、22のプロセスがリスト(Archに基づくManjaro Linux)はファイルを安全に開いていません。

別のシェルで_cat >> ~/.xsession-errors_を実行したときのみ、最終的な出力行にAPフラグが含まれます。

_cat       3099 ravi    1w   REG   W,AP,LG   0,48      963 1926479 .xsession-errors
_

この問題が上流で発生する場所を誰かが知っている場合は、コメントしてください。

実質的に

すべてのプロセスが次のいずれかを使用してファイルをローカルで開く場合:

  • open(2)およびフラグ_O_APPEND_
  • fopen(3)および_"a"_フラグ
  • POSIX sh _>>_ またはbash _&>>_

次に、競合状態によってデータが上書きされることはありません。

@ Gilles answer に感謝します。

2
Tom Hale