Trying to understand pipes - Can't pipe output from tail -f to grep then grep again
Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Trying to understand pipes - Can't pipe output from tail -f to grep then grep again
Hi,
I have a log file, /tmp/GizzyLogs/2008-06-04 which is open and being written to.
I can pipe the output of 'tail /tmp/GizzyLogs/2008-06-04 ' to 'grep 134' and the output of this to 'grep SDSOffice'. As expected, the lines that contain both '134' and 'SDSOffice' are output.
Code:
[root@www ~]# tail /tmp/GizzyLogs/2008-06-04 | grep 134 | grep SDSOffice
134 2008-06-04T12:25:39.173+01:00 www gse: DISCONNECTING FROM CAMERA Site: SDSOfficeTest Camera: Dome User: GrahamTest
[etc...]
I want the output to continue as the file grows, so I try
Are you sure that it works with one grep? tail -f seems to stay live while the file is open (I tried with a log file, and tail -f just outputs added lines as they are written in addition to the original tail). In other words, tail -f doesn't seem to act as an incremental command which is what you seem to me after.
Perhaps it does work that way if the file is actually closed - I won't claim to follow the man page on this point too well.
I tried this too, tail -f with a single grep works but stays alive. I think that's what he wants, because when I run it in the background and add more lines to the file, grep catches it and displays it.
lostjohnny, I don't know why one pipe works but two doesn't, but have you considered grepping both your words in a single grep command using a regex? This works for me:
Code:
tail -f temp.txt | grep '134.*SDSOffice'
If you are expecting the order to be interchanged, i.e. SDSOffice...134, then it looks like you'll have to use egrep:
Yep. I've tried it again to be sure, but the output in my original message is copied and pasted from my terminal emulator.
Quote:
tail -f seems to stay live while the file is open (I tried with a log file, and tail -f just outputs added lines as they are written in addition to the original tail). In other words, tail -f doesn't seem to act as an incremental command which is what you seem to me after.
Perhaps it does work that way if the file is actually closed - I won't claim to follow the man page on this point too well.
I want to "follow" the file - i.e. see the new output as it appears, but I want to filter the results. I use CTRL-C when I'm finished.
2 pipes should work.
Either you are unlucky and the message didn't appear when you did 2 pipes, or the second grep (SDSOffice) is wrong.
Check that you didn't put any unprintable character in the second grep.
I tried this too, tail -f with a single grep works but stays alive. I think that's what he wants, because when I run it in the background and add more lines to the file, grep catches it and displays it.
lostjohnny, I don't know why one pipe works but two doesn't, but have you considered grepping both your words in a single grep command using a regex? This works for me:
Code:
tail -f temp.txt | grep '134.*SDSOffice'
If you are expecting the order to be interchanged, i.e. SDSOffice...134, then it looks like you'll have to use egrep:
Thanks for the solution to my immediate problem, arungoodboy. However, I'd still really like to understand how grep can sometimes (or "often" or "usually" ) pipe to grep, but not in this case. It contradicts my understanding of pipes, which may be simplistic, but aren't pipes simple things?
I thought there'd be a way to do it in one grep statement - I've used the OR operator before (which just happens to be the same as the pipe symbol and needs to be escaped - nothing to do with this problem). I did a quick search for easy-to-read resources that would tell me how to AND, but it was lunch-time so I thought I'd come back to that after lunch. So you've saved me the effort of finding out how to effectively do an AND operation, which could have turned out to be quite substantial - don't know how long it would have taken me to think of using wildcards and realise it was the only/best way to do it. Thanks for that.
Lost Johhny
Last edited by lostjohnny; 06-04-2008 at 09:11 AM.
2 pipes should work.
Either you are unlucky and the message didn't appear when you did 2 pipes, or the second grep (SDSOffice) is wrong.
Check that you didn't put any unprintable character in the second grep.
I don't think there's anything wrong with my second grep. I tried the statement with boths greps first - no output. Then used the command history to repeat the command, but deleted the first grep - output as required:
That must be a buffer issue or something. I never saw anything like that, although I use double pipes quite often. If you find what it is, please tell me.
There's nothing a little googling can't solve! The root cause is grep's behaviour, not the pipes'. Apparently grep buffers the results so you won't (or may not) get the output instantaneously. The argument --line-buffered to the first grep solves your problem.
I've used double pipes successfully. As mentioned, its a buffering issue. In fact, if the logger is busy/frequent, you won't notice the buffering issue ie you won't need the --line-buffered (or you can just be patient ).
There's nothing a little googling can't solve! The root cause is grep's behaviour, not the pipes'. Apparently grep buffers the results so you won't (or may not) get the output instantaneously. The argument --line-buffered to the first grep solves your problem.
I'm still not entirely sure why grep (the first one) would buffer when its output is piped to another grep and not when the output is stdout, but I'm prepared to accept for now that it just does. Maybe it's something to do with how grep (the second one in this case) gets its input. It doesn't challenge my fundamental understanding of pipes, anyway.
Both greps buffer (in fact all cmds do, seaprately), so the more cmds you pipe together, the bigger the effective buffer. Of course they flush when the cmd completes (although tail -f doesn't 'complete', as mentioned above).
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.