MacOSのターミナルのopen
コマンドまたはWindowのターミナルのstart
を模倣する場合、 this answer のコメントは、~/.xsession-errors
にstdoutとstderrを追加することを提案します。(bash
):
alias open='&>>~/.xsession-errors xdg-open'
これで私が予見する問題は競合状態です。 lsof ~/.xsession-errors
は、22プロセスが書き込み用にファイルを開いていることを示しています。
2つのプロセスが~/.xsession-errors
の同じオフセットに書き込むのを防ぐにはどうすればよいですか?
ファイルが追加モードで開かれると、OSはすべての書き込みが最後に行われることを保証します。したがって、あるライターからのデータが別のライターからのデータを上書きすることはありません。
これは、ファイルが追加モードで、つまりシェルで>>
を使用して開かれた場合にのみ適用されます。ファイルの作成者が>
でファイルを開いた場合、その保証は適用されず、次のようなシーケンスになる可能性があります。
>out
;現在位置0>>out
;現在位置0hello
を書き込みます。現在、位置6にありますworld
を書き込みます。これは位置6に書き込まれ、プロセス2は位置12にあります。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"
_フラグsh
_>>
_ またはbash
_&>>
_次に、競合状態によってデータが上書きされることはありません。
@ Gilles answer に感謝します。