「tail -f」ですが、コンテンツを継続して出力せずに再作成(ダウンロード)されるファイルにありますか?

「tail -f」ですが、コンテンツを継続して出力せずに再作成(ダウンロード)されるファイルにありますか?

cronジョブを介してログファイルをダウンロードしました。リモートの場所でファイルが更新されると、データのみを追加してもローカルコピーが最初から書き換えられます。

tail -fまたは同じツールsinceこれを「ファイルが置き換えられました」として扱い、最初からやり直すようです。つまり、既知のすべてを繰り返します。特に、これら2つのツールはSTDERRでこれを明示的に述べています。

したがって、端末から呼び出すと次のようになります。

for j in $(seq 2 4) ; do for i in $(seq 1 $j) ; do echo $i ; sleep 1; done > /tmp/foo; done

tail -f /tmp/footail -F /tmp/foo端末と他の端末の両方で、次の警告が表示されます。

1
2
tail: /tmp/foo: file truncated
1
2
3
tail: /tmp/foo: file truncated
1
2
3
4

を使用すると、次のいずれかのwhile sleep 0.25; do since /tmp/foo; doneエラーメッセージが表示されます。

1
2
since: considering /tmp/foo to be truncated, displaying from start
1
2
3
since: considering /tmp/foo to be truncated, displaying from start
1
2
3
4

sinceファイル名の代わりにinodeを明示的にファイルキーとして使用します。tail切り捨てられたファイルを識別するのと同様の操作を実行できます。

私が試したもう一つの「ツール」はPerlライブラリでした。ファイル::尾しかし、同じ「問題」があり、警告はありません(少なくともデフォルト設定では)。

だから気になります。 inodeを見ずにファイルの内容だけを見て、データがまだ添付されていない場合にのみ再起動する方法やツールはありますか?

私が望むのは次の出力です。

1
2
3
4

(私は見たことがありますtail -f ただし、ファイルが削除され、再生成される場合(追加なし)しかし、それでもファイルの内容を最初からやり直すので役に立ちません。 )

はい、そのようなツールには、表示されているすべての(切り捨てられていない)データのキャッシュ、または少なくともそのデータのハッシュ合計が必要であることがわかります。

答え1

これはtailあなたのユースケースに比べてスマートです。ここでは、次のことができます。

{
  tail
  while cat; do
    sleep 1
  done
} < /tmp/foo

tail-f1980年SysIIIに追加されました)の元の実装と同じです。

catsleep組み込みコマンドを組み込んだシェルまたは組み込みコマンドを使用することをお勧めします。またはperl/で実行してくださいpython

たとえば、デフォルトで組み込まれているksh93場合は、組み込み関数を使用して有効にできます。では、次の代わりにinループを使用できます。sleepcatbuiltin catzshsysreadcatzselectsleep

zmodload zsh/zselect
zmodload zsh/system
readall() while sysread -s 65536 -o1; do continue; done

{
  tail
  while readall; do
    zselect -t 100
  done
} < /tmp/foo

毎回新しいファイルを作成すると、検出tail -fされません。この場合でも、次のことを行うことができます。

#! /bin/zsh -
zmodload zsh/zselect
zmodload zsh/system
readall() while sysread -s 65536 -o1; do continue; done

file=${1-/tmp/foo}
{
  tail
  (( offset = systell(0) ))
} < $file || exit
while true; do
  if
    sysopen -ru0 -- $file 2> /dev/null &&
      sysseek $offset &&
      readall
  then
    (( offset = systell(0) ))
  fi
  zselect -t 100
done

ファイルを再度開き、各反復で最後に知られているオフセットを探します。

関連情報