`tail -f`は最後の行を部分的に消費し、改行やnullを気にしません。

`tail -f`は最後の行を部分的に消費し、改行やnullを気にしません。

一時ファイル(いいえfifo / pipe)は複数のリーダースクリプトで監視する必要があります。各スクリプトは、次のコードを使用してバックグラウンドプロセスを使用して一時ファイルを監視します。

function file_relay {
    # $1 is a regular file to read from
    local bg_file
    bg_file="$1"

    # $2 is a fifo to relay to
    local outfile
    outfile="$2"

    tail -f "$bg_file" | while read -r line
    do
        [[ ! -z "$line" ]] && { printf "%s" "$line" >>"$outfile"; }
    done
}

起動時にファイル全体を読み取り、上記の関数が実行する新しい行を監視する必要があります。

file_relay /tmp/examplefile /tmp/examplefifo &

各スクリプトはまた、このファイルに行を出力します。したがって、これは複数の著者と複数の読者の状況です。

問題は、ファイルにリダイレクトを使用し、文字列の末尾に改行文字があっても完全な行がtail -f使用できるまで待たないことがあることです。printfこれにより、読んでいる行が破損し、最後の行の最初の単語が前の行の最後に追加され、次のような結果が得られます。

This is one lineThis

変える

This is one line
This is another line

解決しようとしているprintfバッファリングの問題tail -fとファイルの周りに書き込みを使用すること(上記の関数ではファイルは読み取り専用なので、ファイル全体をsync読み取ろうとする前にその行を強制的にtail実行する方法がわかりませんsync)。stdbufどこにも影響を与えないようで、-zforまたは文字列をwithまたはotherとして使用または終了するtailことも同様です。$'\0'すぐに発生するのを防ぐ唯一の方法は、ループが始まるsync前ですwhileが、ループが始まっても発生するのを防ぎません。

tail -f強制的に行全体を読むようにする方法はありますか?

答え1

短い:直接ではありません

長い:移植性がない。POSIX)、しかしLinuxにのみ興味があるなら、パイプを通して出力tail -f何かを通してはいラインバッファリング。たとえば、提案したようにUnixコマンド 'tail'に '--line-buffered'オプションはありません。、GNU grepには--line-buffered次のことができるオプションがあります。

tail -f "$bg_file" | grep --line-buffered -E '^.*$'

しかし手動指摘

--line-buffered
ラインバッファリングを使用してください。これはパフォーマンスが低下する可能性があります。

FreeBSD同じオプションと説明があります。オープンBSD 2004、いいえPOSIXしかし…)。

文書にはこれについては記載されていませんが、2001年に初めて提出されました私はそれをするのに時間がかかりましたfflush

関連情報