Eu pensei que tinha visto tudo no UNIX. Esta pergunta me tirou da minha presunção. Que ótima pergunta!
tailmostra as últimas X linhas. tail -ffaz 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, taildeve ser capaz de localizar o final do arquivo. Se tailnã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 tailfaz 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 tailas últimas linhas de um canal do sistema de arquivos. Considerar:
$ mkfifo test.pipe
$ tail test.pipe
stdbufcontornar 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_linescomentá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. headnã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 sede awknão precisam nem do início nem do fim do arquivo: elas funcionam em buffers.