Eu pensei que tinha visto tudo no UNIX. Esta pergunta me tirou da minha presunção. Que ótima pergunta!
tail
mostra as últimas X linhas. tail -f
faz o mesmo, mas essencialmente em um loop infinito: na inicialização, mostre as últimas X linhas do arquivo e, em seguida, use alguma mágica do SO (como inotify), monitore e mostre novas linhas.
Para fazer seu trabalho, tail
deve ser capaz de localizar o final do arquivo. Se tail
não conseguir encontrar o final do arquivo, ele não poderá mostrar as últimas linhas X, porque "last" não está definido. Então, o que tail
faz neste caso? Espera até encontrar o final do arquivo.
Considere isto:
$ chatter() { while :; do date; sleep 1; done; }
$ chatter | tail -f
Isso nunca parece fazer progresso, porque nunca existe um final definido de arquivo chatter
.
Você obtém o mesmo comportamento se solicitar tail
as últimas linhas de um canal do sistema de arquivos. Considerar:
$ mkfifo test.pipe
$ tail test.pipe
stdbuf
contornar o problema percebido foi uma tentativa nobre. O fato principal é que o buffer de E / S não é a causa principal: a falta de um final de arquivo definido é. Se você verificar o código-fonte tail.c , verá o file_lines
comentário da função:
END_POS é o deslocamento do arquivo EOF (um maior que o deslocamento do último byte).
e essa é a mágica. Você precisa de um final de arquivo para que o tail funcione em qualquer configuração. head
não possui essa restrição, apenas precisa do início do arquivo (o que pode não ter, tente head test.pipe
). As ferramentas orientadas para o fluxo gostam sed
e awk
não precisam nem do início nem do fim do arquivo: elas funcionam em buffers.