21

I have configured rsyslog to log certain log events to /dev/xconsole:

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

/dev/xconsole is a named pipe (fifo). If I want to see what is being logged, I can do cat /dev/xconsole. I am surprised to see, that the command cat /dev/xconsole does not finish after reading the file, but instead acts as tail -f. in other words, the two commands behave the same:

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

Can somebody please explain why is that?

Is there any difference between the two?

3 Answers 3

26

cat keeps reading until it gets EOF. A pipe produces EOF on the output only when it gets EOF on the input. The logging daemon is opening the file, writing to it, and keeping it open — just like it does for a regular file — so EOF is never generated on the output. cat just keeps reading, blocking whenever it exhausts what's currently in the pipe.

You can try this out yourself manually:

$ mkfifo test
$ cat test

And in another terminal:

$ cat > test
hello

There will be output in the other terminal. Then enter:

world

There will be more output in the other terminal. If you now Ctrl-D the input then the other cat will terminate too.

In this case, the only observable difference between cat and tail -f will be if the logging daemon is terminated or restarted: cat will stop permanently when the write end of the pipe is closed, but tail -f will keep going (reopening the file) when the daemon is restarted.

4
  • sorry I don't see where "world" will come from in your example :) Jul 8, 2017 at 3:30
  • From your typing it in. Jul 8, 2017 at 3:32
  • 1
    And then you type world, and, lo, "world" appears in the other terminal. Jul 8, 2017 at 3:34
  • "but tail -f will keep going..." Is it because contrary to cat, tail -f will ignore EOF conditions and will only stop permanently when one enters Ctrl+C (i.e. when receiving an interrupt signal)?
    – The Quark
    Nov 1, 2021 at 8:59
3

There is also a difference in buffering between cat and tail -f. You can check this out:

Create pipe: mkfifo pipe

Start reading pipe using cat in background: cat pipe &

Open pipe and write to it every second: perl -MFcntl -we 'sysopen(my $fh, "pipe", O_WRONLY | O_NONBLOCK); while() {warn "written: " . syswrite($fh, "hello\n"); sleep 1}'

Now try this with tail -f pipe & instead of cat. So you can see that cat prints lines as soon as they are written to pipe by perl script, while tail -f buffers them up to 4kb before printing to stdout.

-4

cat shows you the whole file when tail -f Shows only the last rows and follows. So if the file is short they behave the same, but if the file is big (100+ rows) you can see a clear difference between them two.

Additional information about those commands :

tail http://www.computerhope.com/unix/utail.htm

cat http://www.computerhope.com/unix/ucat.htm

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .