FIFOを介してログに記録し、ファイルにリダイレクトしますか?


8

各トランザクションをログに記録する必要があるアプリケーションがあります。クラッシュに至るまでに何が起こったかを記録する必要があるため、すべてのログメッセージがフラッシュされます。同僚と私は、ログメッセージがプロセスを離れたことを保証しながら、バッファリングのパフォーマンス効果を達成する方法に興味を持っていました。

私たちが思いついたのは:

  • アプリケーションが書き込み可能なFIFOを作成し、
  • 経由でそのFIFOの内容を通常のファイルにリダイレクトしますcat

つまり、通常は次のとおりでした。

app --logfile logfile.txt

今でしょ:

mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo

このアプローチに落とし穴はありますか?テスト時に機能しましたが、元のアプリケーションがクラッシュした場合でも、メッセージがリダイレクトファイルに到達することを確実に確認したいと考えています。

(アプリケーションのソースコードがないため、プログラミングソリューションは問題外です。また、アプリケーションはに書き込みを行わないstdoutため、別のコマンドに直接パイプすることは問題外です。そのsyslogため、可能性はありません。)


更新:バウンティを追加しました。受け入れ答えはなりません伴うlogger単純な理由loggerはない私が尋ねたもの。元の質問が述べているように、私はFIFOを使用する上での問題点のみを探しています。


これまでのいくつかの回答には、非常に大きな混乱があるようです。私が最初に私の質問で強調したように、私はログを記録する仲介者としてFIFOを使用するアプローチへの落とし穴を探しています。私は少なくとも私の元の質問の落とし穴を探求しない代替案には興味がありません。
chrisaycock

stdoutへのロギングに関する私の答えがあなたが興味のある方向ではない場合、おそらく「アプリケーションはstdoutに書き込まないため、別のコマンドに直接パイプすることは問題外です」という質問を削除できますか?
ニックグリム2012

回答:


6

書き込まれた量が読み取られた量を超える可能性があるプログラミングでは、通常fifoが必要であることに注意してください。

そのため、FIFOは予想どおりに完全にスムーズに機能するわけではありませんが、別の機能を導入しながら主な問題を解決します。

考えられる警告が3つあります。

  1. 初期化時に他端を読み取っていない場合、FIFOへの書き込みは無期限にブロックされます。
  2. fifoの幅は64Kに固定されており、そのポイントまでにバッファーがいっぱいになると、リーダーが追いつくまで書き込みがブロックされます。
  3. パイプライターは、リーダーが停止または終了した場合にSIGPIPEで強制終了されます。

これは、問題(非バッファー書き込みでのバッファーI / Oのエミュレート)が解決されることを意味します。これは、FIFOの新しい「制限」が、パイプにあるものをディスクに書き込むユーティリティの速度(おそらくバッファリングされたI / O)になるためです。

それにもかかわらず、ライターは機能するためにログリーダーに依存するようになります。リーダーが突然読むのをやめると、ライターはブロックします。リーダーが突然終了した場合(ターゲットのディスク領域が不足したと表示されます)、ライターはSIGPIPEで終了します。

もう1つ言及する必要があるのは、サーバーがパニックになり、カーネルが応答を停止した場合、そのバッファーにあった最大64kのデータが失われる可能性があることです。

これを修正する別の方法は、tmpfs(Linuxでは/ dev / shm)にログを書き込み、固定ディスクの場所に出力をテールすることです。これを行うメモリ割り当てにはそれほど制限はありませんが(64Kではなく、通常は2G!)、ライターがログファイルを動的に開く方法がない場合は機能しない可能性があります(tmpfsからログを定期的に削除する必要があります)。この方法でサーバーがパニックになると、さらに多くのデータが失われる可能性があります。


これはに関するいくつかの良い情報/dev/shmです。私もそれを考えていましたが、使用するのに頭がおかしくなりましたtail -f
chrisaycock

4
mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo

cat logfifoプロセスが停止した場合、誰かが誤ってプロセスを終了した場合、または誰かが誤ってプロセスを間違った場所にポイントした場合はどうなりますか?

私の経験では、appはすぐにブロックしてハングします。私はこれをTomcat、Apache、およびいくつかの小さな自家製のアプリケーションで試しましたが、同じ問題に遭遇しました。logger単純なI / Oリダイレクションで思い通りの結果が得られたので、あまり遠くまで調査しませんでした。通常、ログの完全性は必要ありません。これは、追跡しようとしていることです。そして、あなたが言うように、あなたはロガーを望んでいません。

Linuxのノンブロッキングfifo(オンデマンドロギング)でこの問題についての議論があります。


面白い。それでアプリはとにかくブロックする可能性がありますか?この時点で、タオルを投入してFusion IOを注文することを検討しています。
chrisaycock

試してみる。私にとって、この結果はすぐに起こりました(低スペックのハードウェアのテスト環境で)。これはUbuntuとRedHat 5で発生しました。FreeBSDなどが同様の動作をするかどうかは不明です。
Stefan Lasiewski、2012

2

オプションはアプリによってかなり制限されていますが、テストしたものは機能します。

varnishとvarnishncsaでも同様のことを行って、ログをどこかで取得します。私たちはfifoを持っていて、syslog-ngでそれを読み取り、必要な場所に送信します。私たちは約50GBを処理し、このアプローチでこれまで問題に遭遇していません


かっこいい、これを思いついたのは私たちだけではない。
chrisaycock

2

環境はCentOSであり、アプリケーションはファイルに書き込みます...

通常のファイルに送信する代わりに、出力をsyslogに送信し、syslogメッセージがローカルだけでなく中央サーバーにも送信されていることを確認します。

次のようなシェルスクリプトを使用できるはずです。

logger -p daemon.notice -t app < fifo

パイプloggerから、catまたはtail -fパイプに(から)入力を取得することもできます。

tail -f fifo | logger ...
cat fifo | logger ...

唯一の問題は、ログメッセージの重要性(すべてがNOTICE)に基づいて区別されないことですが、少なくともログに記録され、オフホストで中央サーバーに送信されます。

syslogの構成は、使用しているサーバーによって異なります。あるrsyslogsyslog-ng(両方とも非常に可能)。

編集:ポスターからより多くの情報を得た後に改訂されました。


ログメッセージは選択可能なファイルに書き込まれますが、アプリケーションはに書き込みませんstdout。OSはCentOSです(質問にlinuxのタグを付けましたが、見落としがちです)。すべてのメッセージの重要性は同じであるため、このアプリケーションでは通知とエラーに違いはありません。
chrisaycock

通知とエラーに違いはありませんか?ああ、本当に?間に違いないSlow query detectedDatabase halted
メイ

(私は投稿を更新しました。)
Mei

1

あなたが書く:

また、アプリケーションは書きませんstdout...

「ファイル」にログインしてみました/dev/stdoutか?これにより、次のようなことが可能になる場合があります。

app --logfile /dev/stdout | logger -t app

FIFOとは異なりますか?落とし穴は何ですか?それ自体、私は代替手段を探していません。私が挙げたアプローチが堅牢であるかどうかについての洞察を探しています。それは私がに興味がすべてです。
chrisaycock

1
はい、FIFOとは異なります。STDOUTに接続されているファイルです。そのため、これを使用してSTDOUTにログを記録し、そこからsyslogまたは同様のログに記録できます。これは元の問題の解決策として意図されていますが、可動部分が少ないため、FIFOよりも堅牢であることを願っています。
ニックグリム

1

fifoに書き込んでから、別のプロセスにファイルに書き込むようにしても意味がありません。通常どおりファイルに直接書き込むだけで、write()戻ってきたらカーネルの手に渡ります。アプリケーションがクラッシュした場合でも、ディスクに書き込まれます。


すべてのログメッセージがフラッシュされます。これらは書き込みをブロックしています。アプリケーションのソースコードがないので、それを制御することはできません。
chrisaycock

@chrisaycock、そう...問題はどこにあるの?
psusi

同僚と私は、ログメッセージがプロセスを離れたことを保証しながら、バッファリングのパフォーマンス効果を達成する方法に興味を持っていました。
chrisaycock

@chrisaycockああ、それでアプリケーションは現在O_SYNCを使用するかfsync()、各書き込みがディスクにヒットするのを待つので、それを実行したくない(システムクラッシュの場合に損失が発生する危険性がある)?
psusi

1
@chrisaycock、それはドライブのインターフェースとは何の関係もありません。それは通常、カーネルがそれをファイルシステムキャッシュに(そしてアプリケーションから)コピーしたことを意味します。最初に私の回答で述べたように、write()が返されると、アプリは好きなだけクラッシュする可能性があります-カーネルがクラッシュしない限り、データはディスクに移動します。
psusi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.