leitura contínua de pipe nomeado (gato ou cauda -f)

16

Eu configurei rsyslogpara registrar certos eventos de log em /dev/xconsole:

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

/dev/xconsoleé um pipe nomeado ( fifo). Se eu quiser ver o que está sendo registrado, eu posso fazer cat /dev/xconsole. Estou surpreso ao ver que o comando cat /dev/xconsolenão termina depois de ler o arquivo, mas age como tail -f. em outras palavras, os dois comandos se comportam da mesma maneira:

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

Alguém pode explicar por que isso?

Existe alguma diferença entre os dois?

Martin Vegter
fonte

Respostas:

18

catcontinua lendo até obter EOF. Um tubo produz EOF na saída somente quando obtém EOF na entrada. O daemon de log está abrindo o arquivo, gravando nele e mantendo-o aberto - assim como acontece com um arquivo comum - para que o EOF nunca seja gerado na saída. catapenas continua lendo, bloqueando sempre que esgota o que está atualmente no tubo.

Você pode tentar fazer isso manualmente:

$ mkfifo test
$ cat test

E em outro terminal:

$ cat > test
hello

Haverá saída no outro terminal. Então:

world

Haverá mais saída no outro terminal. Se você agora pressionar Ctrl-D a entrada, a outra catterminará também.

Nesse caso, a única diferença observável entre cate tail -fserá se o daemon de log for encerrado ou reiniciado: catserá interrompido permanentemente quando a extremidade de gravação do pipe for fechada, mas tail -fcontinuará (reabrindo o arquivo) quando o daemon for reiniciado.

Michael Homer
fonte
desculpe, eu não vejo onde "mundo" virá no seu exemplo :)
Alexander Mills
Da sua digitando-o.
Michael Homer
1
E então você digita worlde, eis que "world" aparece no outro terminal.
Michael Homer
2

Há também uma diferença no buffer entre cate tail -f. Você pode verificar isso:

Criar canal: mkfifo pipe

Comece a ler o pipe usando catem segundo plano:cat pipe &

Abra o pipe e escreva nele a cada segundo: perl -MFcntl -we 'sysopen(my $fh, "pipe", O_WRONLY | O_NONBLOCK); while() {warn "written: " . syswrite($fh, "hello\n"); sleep 1}'

Agora tente isso com em tail -f pipe &vez de cat. Assim, você pode ver que catimprime linhas assim que são gravadas no canal por script perl, enquanto as tail -f armazena em buffer até 4kb antes de imprimir em stdout.

Interessado em
fonte