3

I have a process that is writing to standard out, and I want to be able to monitor the output by grepping for various strings while running tail -f. One way to do this is to write to a normal file and then tail the file grepping for one string, then tail it grepping for another. However, I don't want to write to a file because this will fill up the disk, and I don't want to deal with the hassle of rotating log files.

I thought I could achieve this using fifos. E.g.,

mkfifo myfifo
foo > myfifo &
tail -f myfifo | grep bar
tail -f myfifo | grep baz

Unfortunately, this doesn't seem to work. In fact, the only way I see any output when tailing is when I first execute tail -f myfifo and then foo > mfifo, but I don't want to restart foo (that's the whole point, otherwise I can just grep standard out directly and restart the process to grep for a different string). Does anyone know why this is happening or have a suggestion for how to achieve this?

jonderry
  • 23,013
  • 32
  • 104
  • 171

2 Answers2

4

This is happening because a fifo is a data stream. Once a piece of data is read from a FIFO, it's removed from the FIFO. In your case, the output of foo that's stored in myfifo is being read by the first tail -f that greps for "bar", leaving nothing for the second tail -f.

But you don't need to send the output of foo to a file at all (FIFO or otherwise). You can just send its output directly into tee and have it send that output to as many processes as you want. For example:

$ foo | tee >(grep -o bar) >(grep -o baz) >/dev/null

Or if you're just using grep, you can use -e as many times as you want on the output:

$ foo | grep -e bar -e baz
Community
  • 1
  • 1
Christopher Neylan
  • 8,018
  • 3
  • 38
  • 51
  • +1 thanks, this is useful, but in my case I don't necessarily know what I will be grepping beforehand. What I was hoping to do was have a way of grepping the output of a long-running process when I see something I want to pull out. Regarding your comment about the fact that a fifo is a data stream, does that prevent it from being read by another process even after the first reader is killed (e.g., tail -f foo | grep bar -C tail -f foo | grep baz)? – jonderry Apr 18 '13 at 21:33
1

You can use a different grep syntax:

tail -f myfifo | grep -e 'pattern1' -e  'pattern2' -e 'pattern3'

I think you want both to happen at the same time on the same output stream, right?

Otherwise you could play with tee

tail -f myfifo | tee -a somefile | grep bar
grep foo somefile
jim mcnamara
  • 16,005
  • 2
  • 34
  • 51