Por que o comando a seguir não produz nenhuma saída?
$ tail -f /etc/passwd | tail
Depois de ler sobre o buffer , tentei o seguinte sem sucesso:
$ tail -f /etc/passwd | stdbuf -oL tail
Observe que o seguinte produz saída:
$ tail /etc/passwd | tail
O mesmo acontece com isso:
$ tail -f /etc/passwd | head
Estou usando a versão cauda 8.21 (GNU coreutils).
Respostas:
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. Setail
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 quetail
faz neste caso? Espera até encontrar o final do arquivo.Considere isto:
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: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á ofile_lines
comentário da função: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, tentehead test.pipe
). As ferramentas orientadas para o fluxo gostamsed
eawk
não precisam nem do início nem do fim do arquivo: elas funcionam em buffers.fonte
tail -f
O rabo de na verdade é algo desconhecido no presente, então como o próximo devetail
saber. Por outro ladotail -f
, a cabeça já é algo conhecido e pode ser processado.Ou, para simplificar:
tail
é relativo ao final do arquivo, mas o fluxo de saídatail -f
não possui EOF (pelo menos não antes de seu término).Se você encontrar a primeira
tail
's pid e matá-lo, você deve então ver a saída do segundo.fonte
Resposta técnica
Ao executar com um fluxo como entrada,
tail
mantém umn
buffer de linha que ele preenche ao ler o fluxo, mas não pode gerar essas linhas até chegar ao final do fluxo, ou seja, recebe umEOF
código especial ao tentar ler a entrada corrente. A invocaçãotail -f
não sai e, portanto, nunca fecha seu fluxo, o que torna impossível, por exemplo, retornar as 10 últimas linhas desse fluxo.fonte
A função de
tail
é mostrar a última parte - "cauda" - da entrada ou arquivo. (A opção-f
é sobre o que faz depois, para que não seja relevante aqui.)Vamos pensar em um arquivo:
Qual é a última parte de um arquivo ?
Digamos que sejam as últimas n linhas de um arquivo.
Quando lemos a linha
i
do arquivo de entrada, como decidir se ele precisa ser impresso ou não?Não sabemos se está na última parte - porque não sabemos qual será a última linha. Portanto, não podemos imprimi-lo agora.
Precisamos manter a linha até que fique claro que é parte dos últimos
n
linhas, ou que não pode mais fazer parte dela, porque sabemosn
outras linhasSe agora chegamos ao final do arquivo , sabemos que as últimas
n
linhas que mantemos são, de fato, as últimasn
linhas do arquivo.Agora, no caso de
o primeiro
tail
lê o arquivo e, em seguida, espera obter mais dados dele para escrevê-lo também. Portanto, ele não sinalizará o final do arquivo para a segunda cauda quando chegar ao final do arquivo que ele lê. Sem isso, o segundotail
nunca é notificado sobre o final do arquivo, portanto nunca pode descobrir quais são as últimas linhas que deve imprimir.fonte