Pourquoi “tail -f… | "queue" ne produit aucune sortie?

36

Pourquoi la commande suivante ne produit aucune sortie?

$ tail -f /etc/passwd | tail

Après avoir lu des informations sur la mise en mémoire tampon , j’ai tenté en vain de procéder comme suit:

$ tail -f /etc/passwd | stdbuf -oL tail

Notez que ce qui suit produit une sortie:

$ tail /etc/passwd | tail

Ainsi fait ceci:

$ tail -f /etc/passwd | head

J'utilise la version de queue 8.21 (GNU coreutils).

thomie
la source
17
Quels sont les 10 derniers chiffres de π?
Keith Thompson

Réponses:

15

Je pensais avoir tout vu dans UNIX. Cette question m'a giflé de ma suffisance. Quelle belle question!

tailmontre les dernières X lignes. tail -ffait la même chose, mais essentiellement dans une boucle infinie: au démarrage, montre les X dernières lignes du fichier, puis en utilisant une magie de système d’exploitation (comme inotify), surveille et affiche de nouvelles lignes.

Pour faire son travail, tailil faut pouvoir localiser la fin du fichier. Si tailvous ne trouvez pas la fin du fichier, il ne peut pas afficher les X dernières lignes, car "last" n'est pas défini. Alors, que fait tail-on dans ce cas? Il attend jusqu'à ce qu'il trouve la fin du fichier.

Considère ceci:

$ chatter() { while :; do date; sleep 1; done; }
$ chatter | tail -f

Cela ne semble jamais progresser, car il n’existe jamais de fin de fichier définitive chatter.

Vous obtenez le même comportement si vous demandez tailà vous donner les dernières lignes d'un canal de système de fichiers. Considérer:

$ mkfifo test.pipe
$ tail test.pipe

stdbufcontourner le problème perçu était une noble tentative. Cependant, l’essentiel est que la mise en mémoire tampon des E / S ne soit pas la cause première: il n’ya pas de fin de fichier définie. Si vous extrayez le code source tail.c , le file_linescommentaire de la fonction se lit comme suit:

END_POS correspond au décalage de fichier de EOF (supérieur à celui du dernier octet).

et c'est la magie. Vous avez besoin d'une fin de fichier pour que tail puisse fonctionner dans n'importe quelle configuration. headn'a pas cette restriction, il faut juste un début de fichier (ce qui pourrait ne pas l'avoir, essayez head test.pipe). Les outils orientés flux tels que sedet awkne nécessitent ni début ni fin de fichier: ils travaillent sur des tampons.

évêque
la source
37

tail -fLa queue de est en réalité quelque chose d'inconnu dans le présent, alors comment le prochain devrait le tailsavoir. Par contre, tail -fla tête est déjà connue et pourrait donc être traitée.

Ou pour le dire plus simplement: tailest relative à la fin du fichier, mais le flux de sortie tail -fn'a pas eu de fin de fichier (du moins pas avant sa fin).

Si vous trouvez le premier tailde pid et tuez - le, vous devriez alors voir la sortie de la seconde.

Ghanima
la source
21

Réponse technique

Lors de l'exécution avec un flux en entrée, tailconserve un ntampon de lignes qu'il remplit lors de la lecture du flux, mais il ne peut pas sortir ces lignes tant qu'il n'a pas atteint la fin du flux, c'est-à-dire qu'il reçoit un EOFcode spécial lorsqu'il tente de lire à partir de l'entrée. courant. L'invocation tail -fne se termine pas et ne fermera donc jamais son flux, ce qui rend par exemple impossible le retour des 10 dernières lignes de ce flux.

sleblanc
la source
3

La fonction de tailest d'afficher la dernière partie - "queue" - de l'entrée ou du fichier. (L'option -fconcerne ce qu'elle fait plus tard, ce qui n'est pas pertinent ici.)

Pensons à un fichier:

Quelle est la dernière partie d'un fichier ?
Disons que ce sont les n dernières lignes d'un fichier.

Quand on lit la ligne idu fichier d’entrée, comment décider de l’imprimer ou non?
Nous ne savons pas si c'est dans la dernière partie - parce que nous ne savons pas quelle sera la dernière ligne. Nous ne pouvons donc pas l’ imprimer maintenant.

Nous devons garder la ligne jusqu'à ce qu'il soit clair que cela fait partie des dernières nlignes ou ne peut plus en faire partie, car nous savons que d' nautres lignes

Si nous arrivons maintenant à la fin du fichier , nous savons que les dernières nlignes que nous avons conservées sont en fait les dernières nlignes du fichier.

Maintenant, dans le cas de

tail -f /etc/passwd | tail

le premier taillit le fichier, puis attend d’ obtenir plus de données pour l’écrire également. Donc, il ne signalera pas la fin du fichier à la deuxième queue quand il arrivera à la fin du fichier lu. Sans cela, le second tail ne sera jamais averti de la fin du fichier, il ne pourra donc jamais savoir quelles sont les dernières lignes à imprimer.

Volker Siegel
la source