tail -f
部分消耗最後一行,不關心換行符或 nul
我有一個需要由多個閱讀器腳本監視的臨時文件(**不是fifo/管道)。**每個腳本都使用後台程序來監視臨時文件,使用以下程式碼:
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
’s buffering 、tail -f
’ s buffering 以及 usesync
around writes to the file(文件在上面的函式中是只讀的,我不知道如何在嘗試讀取整個文件之前強制tail
執行sync
線)。stdbuf
似乎在任何地方都沒有任何效果,使用-z
fortail
或終止字元串$'\0'
或其他任何東西也沒有。唯一能阻止它立即發生的是循環開始sync
之前的單while
次,但這並不能阻止它在那之後發生。有沒有辦法強制
tail -f
只讀取完整的行?
短:不直接
long:它不是可移植的(不在POSIX中),但是如果您將興趣限制在 Linux 上,您可以通過線緩衝的方式*輸出。例如,正如unix command ’tail’ lost option ‘–line-buffered’*中所建議的,GNU grep 有一個選項,允許您執行此操作
tail -f``--line-buffered
tail -f "$bg_file" | grep --line-buffered -E '^.*$'
然而,正如手冊指出的那樣
--line-buffered
使用行緩衝,它可能是一種性能懲罰。
(FreeBSD在 2004 年與 OpenBSD 有相同的選項和評論,還沒有POSIX …)。
文件沒有指出這一點,但2001 年的初始送出考慮到了花費在
fflush
.