名前付きパイプの戻り値に対するseek()操作を成功させることは可能ですか?


12

プログラムseek()が名前付きパイプで操作を実行しようとすると、「違法シーク」の代わりに成功します(ただし、パイプが空のファイルであるかのように振る舞う)ようにする方法はありますか?

私のシステムの最後の少しのログはSQLiteデータベースに保存されており、どこにもファイルはありません。ただし、これに問題があるプログラムがいくつかあります。2つの特定のケースがあります。

  • プログラムは、syslog-ngが名前付きパイプとして作成して読み取り中のログファイルに書き込みたいと考えています。プログラムはseek()何らかの理由でaを実行したいのに失敗します。
  • プログラム(denyhostsやfail2banなど)は、syslog-ngが名前付きパイプとして作成して書き込み中のログファイルから読み取りたいと考えています。プログラムはそれを実行しようとしてseek()失敗します。

理想的には、これらのシークが名前付きパイプが単なる空のファイルであるかのように動作するようにしたいのです。とにかく、ログを書き込むプログラムがシークを実行する必要がある理由がわかりません。追加のためにファイルを開いて書き込みを開始するだけです。プログラムの読み取りが最後の位置から再開できるように、プログラム読み取りがシークしたい理由がわかります。したがって、ファイルが空のように(切り捨てられたように)動作するようにします。

名前付きパイプにこのように動作させるために設定できるオプションがありますか?そうでない場合、syslog-ngがパイプを開いてこのように動作させるときに設定できるモードはありますか?それとも、私は小川を上がっていますか?

回答:


10

Linuxカーネル用にシーク可能パイプが提案されていますが、それらを実装するための有効なパッチについては知りません。

特定のファイルの呼び出しLD_PRELOADをオーバーライドする'edライブラリを使用できlseekます。この目的のための既製のラッパーは知りません。Shadowfsは1つを書くのに役立つかもしれません。


1
LD_PRELOADルートを試します。最大の解決策ではありませんが、実行可能でなければなりません。
パトリック

以下のためにところで、あるシーク可能なパイプが必要であろう以下は、それがファイルに従うことができ、同じようにパイプをたどることができるように?私は以下を使用してパイプをフォローするというコンテキストで尋ねていますか?質問(そこに答えることを好むかもしれません)。
ピョートルドブロゴスト

@PiotrDobrogost lessのFコマンドのコンテキストでは、1秒ほど出力が得られない場合、lessは画面を更新するだけで十分です。パイプをシーク可能にしても助けにはなりません。関連する違いFは、ファイルの終わりまで行き、データが終わりを過ぎるのを待つことです。
ジル 'SO-悪であるのをやめる'

1

アプリケーションがシークを呼び出している場合、それは壊れているか、パイプで動作することを意図していません。前者の場合、修正が必要です。後者の場合、シークが実際に機能することを期待しているので、嘘をついてそれが機能しなかったときに機能したと主張すると、ほぼ間違いなく誤った動作を引き起こします。

また、ログファイルが名前付きパイプに置き換えられた場合、一度に1つのプロセスのみがそのファイルから読み取ることができます。代わりにソケットにする必要があります。


2
パイプで動作するように意図されていないことは、パイプで動作しないことを意味しません。アプリケーションがファイルの最後に到達するために単にSEEK_ENDを実行している場合はどうなりますか?または、SEEK_CURを実行して現在の場所を見つけることもできます。シークの結果についてプログラムに嘘をついた場合、これらのどちらも問題を引き起こしません。壊れる唯一の場所は、アプリケーションが戻って、すでに書き込まれているデータを上書きしようとしていた場合です。そして、はい、パイプあたり1プロセスの制限を認識しています。これは問題になりません。
パトリック

1
追加するために最後までシークするだけの場合は、ファイルを追加モードで開くだけなので、壊れたカテゴリーに分類されます。アプリケーションは、他の場所を探す必要がない限り、現在の場所を見つけようとせず、現在の場所に戻るため、「黙って失敗することで破壊する」カテゴリに分類されます。プログラムがseekを呼び出すことはほとんどありませんが、実際に動作する必要はありませ(実行する場合、壊れたカテゴリに分類されます)。
psusi

1
違います。多くのアプリケーションは、他のプログラムが最後にファイルに書き込んだ後にファイルに書き込んだ場合に備えて、ファイルの最後を探します。それ以外の場合、現在の場所に書き込むと、他のプログラムの変更が上書きされます。また、ファイルからの読み取りの場合は、SEEK_CURを使用して現在の場所を取得し、プログラムの起動時に中断したところから再開できるようにします。
パトリック

1
前者の@Patrickは、追加する場合、追加モードでファイルを再度開く必要があります。この場合、読み取りについて話しているのですが、その場合、まだ読み取っていない新しいデータをスキップすることは意味がありません(そして、シークを無視すると静かにそれが壊れます)。後者については、パイプを閉じるときにサーバーがSIGPIPEを取得するため、シークを静かに無視するとパイプで壊れるファイルを閉じて再度開いた後にシークを使用して同じ位置に戻ろうとする場合、おそらく、それをリセットして、パイプを開く次のクライアントが最初から開始するようにします。
-psusi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.