lecture continue de la pipe nommée (cat ou tail -f)

16

J'ai configuré rsyslogpour enregistrer certains événements de journal pour /dev/xconsole:

*.*;cron.!=info;mail.!=info      |/dev/xconsole

/dev/xconsoleest un tube nommé ( fifo). Si je veux voir ce qui est enregistré, je peux le faire cat /dev/xconsole. Je suis surpris de voir que la commande cat /dev/xconsolene se termine pas après la lecture du fichier, mais agit à la place tail -f. en d'autres termes, les deux commandes se comportent de la même manière:

cat /dev/xconsole
tail -f /dev/xconsole

Quelqu'un peut-il expliquer pourquoi?

Y a-t-il une différence entre les deux?

Martin Vegter
la source

Réponses:

18

catcontinue de lire jusqu'à ce qu'il obtienne EOF. Un tuyau produit EOF sur la sortie uniquement lorsqu'il obtient EOF sur l'entrée. Le démon de journalisation ouvre le fichier, y écrit et le maintient ouvert - tout comme il le fait pour un fichier normal - donc EOF n'est jamais généré sur la sortie. catcontinue de lire, de bloquer chaque fois qu'il épuise ce qui est actuellement dans le tuyau.

Vous pouvez l'essayer vous-même manuellement:

$ mkfifo test
$ cat test

Et dans un autre terminal:

$ cat > test
hello

Il y aura une sortie dans l'autre terminal. Alors:

world

Il y aura plus de sortie dans l'autre terminal. Si vous maintenant Ctrl-D l'entrée, l'autre catse terminera aussi.

Dans ce cas, la seule différence observable entre catet tail -fsera si le démon de journalisation est terminé ou redémarré: cats'arrêtera définitivement lorsque l'extrémité en écriture du canal sera fermée, mais tail -fcontinuera (réouverture du fichier) lorsque le démon sera redémarré.

Michael Homer
la source
désolé, je ne vois pas d'où viendra le "monde" dans votre exemple :)
Alexander Mills
De votre saisie.
Michael Homer
1
Et puis vous tapez world, et, lo, "world" apparaît dans l'autre terminal.
Michael Homer
2

Il existe également une différence de mise en mémoire tampon entre catet tail -f. Vous pouvez vérifier ceci:

Créer un tuyau: mkfifo pipe

Commencez à lire le tuyau en utilisant caten arrière-plan:cat pipe &

Ouvrez le tuyau et écrivez-y toutes les secondes: perl -MFcntl -we 'sysopen(my $fh, "pipe", O_WRONLY | O_NONBLOCK); while() {warn "written: " . syswrite($fh, "hello\n"); sleep 1}'

Essayez maintenant avec tail -f pipe &au lieu de cat. Vous pouvez donc voir que les catlignes sont imprimées dès qu'elles sont écrites dans le script pipe par perl, tout en les tail -f tamponnant jusqu'à 4 Ko avant d'imprimer sur stdout.

Intéressé par
la source