次のコマンドで出力が生成されないのはなぜですか?
$ tail -f /etc/passwd | tail
buffering について読んだ後、次のことを試してみましたが、役に立ちませんでした:
$ tail -f /etc/passwd | stdbuf -oL tail
以下は出力を生成することに注意してください。
$ tail /etc/passwd | tail
これもそうです:
$ tail -f /etc/passwd | head
私はテールバージョン8.21(GNU coreutils)を使用しています。
UNIXですべてを見たと思った。この質問は私を独りぼっちから落とした。すばらしい質問ですね。
tail
は、最後のX行を示します。 tail -f
も同じですが、基本的には無限ループです。起動時に、ファイルの最後のX行を表示し、OSのマジック(inotifyなど)を使用して監視し、新しい行を表示します。
tail
がファイルの終わりを見つけられる必要があります。tail
が"last"は未定義であるため、ファイルの最後では、最後のX行を表示できません。この場合、tail
は何をするのでしょうか?ファイルの終わりが見つかるまで待機します。
このことを考慮:
$ chatter() { while :; do date; sleep 1; done; }
$ chatter | tail -f
chatter
からの明確なファイルの終わりは決してないので、これは進歩するようには見えません。
tail
にファイルシステムパイプの最後の行を提供するように要求した場合も、同じ動作が得られます。考慮してください:
$ mkfifo test.pipe
$ tail test.pipe
認識された問題を回避するためのstdbuf
は高貴な試みでした。ただし、重要な事実は、I/Oバッファリングが根本的な原因ではないことです。明確なファイルの終わりがないことが原因です。 tail.cソースコード をチェックアウトすると、file_lines
関数のコメントが次のように表示されます。
END_POSは、EOF(最後のバイトのオフセットよりも1つ大きい)のファイルオフセットです。
それが魔法です。あらゆる構成で機能するには、tailのファイルの終わりが必要です。 head
にはそのような制限はありません。ファイルの開始が必要なだけです(これにはない場合があります。head test.pipe
を試してください)。 sed
やawk
のようなストリーム指向のツールは、ファイルの最初または最後を必要としません。これらはバッファで機能します。
tail -f
の尻尾は現在のところ実際には不明なものなので、次のtail
はどのようにそれを知る必要がありますか。一方、tail -f
の頭はすでに知られているため、処理することができます。
または、もっと簡単に言えば、tail
はファイルの終わりを基準にしていますが、tail -f
の出力ストリームはEOF(少なくとも終了前ではありません) )。
最初のtail
のpidを見つけてそれをkillする場合は、then 2番目の出力を確認してください。
入力としてストリームを使用して実行している場合、tail
はストリームを読み取るときに満たすn
- lineバッファーを保持しますが、ストリームの最後に到達するまでこれらの行を出力できません。入力ストリームから読み取ろうとすると、特別なEOF
コードを受け取ります。呼び出しtail -f
は終了しないため、ストリームを閉じることはありません。そのストリームの最後の10行を返します。
tail
の機能は、入力またはファイルの最後の部分(「テール」)を表示することです。 (オプション -f
は後で何をするかということなので、ここでは関係ありません。)
ファイルについて考えてみましょう:
ファイルの最後の部分とは何ですか?
ファイルの最後のn行だとしましょう。
入力ファイルの行i
を読み取るときに、印刷する必要があるかどうかをどのように判断するのですか?
それが最後の部分にあるかどうかはわかりません-最終行がどちらになるかわからないためです。それでできません今すぐ印刷します。
最後のn
行の一部であることが明らかになるまで、またはn
をさらに知っているため、もはやその行の一部でなくなることができるまで行を保持する必要があります線
ファイルの終わりに到達すると、最後に保持したn
行が実際にファイルの最後のn
行であることがわかります。
さて、の場合
tail -f /etc/passwd | tail
最初のtail
はファイルを読み取り、それからさらにデータを取得するを待って、それも書き込みます。つまり、読み取るファイルの終わりになると、ファイルの終わりを知らせないが2番目の末尾に追加されます。それがなければ、ファイルの終わりの2番目のtail
通知されないなので、出力できる最後の行である決してわかりませんです。