8

I am trying to pipe tail -f into awk to monitor a logfile in realtime, but according to examples, there should be not problem but I can't get it to work.

here is the command I'm running

tail -f logfile.log | awk -F" " '{print $1, $2, $7, $8}'

But when I edit my file using nano add a line, it is not printed in real time, If I run the awk command directly, my new line appear in the result.

10

You don't see it in real time because, for purposes of efficiency, pipes are buffered. tail -f has to fill up the buffer, typically 4 kB, before the output is passed to awk.

A fix is to use the unbuffer command which is part of the expect package:

unbuffer tail -f logfile.log | awk -F" " '{print $1, $2, $7, $8}'

This tricks tail into thinking it is writing to an interactive terminal. As a result, it doesn't buffer.

For more, see https://unix.stackexchange.com/questions/25372/turn-off-buffering-in-pipe

Alternatively, if you have GNU coreutils 7.5 or better, you can disable output buffering with the stdbuf command:

stdbuf -o0 tail -f logfile.log | awk -F" " '{print $1, $2, $7, $8}'
  • Sadly the stdbuf solution does not seem to work either. – gimpycpu Apr 16 '14 at 3:22
  • But you are right that if I add ~10 rows, the buffer is flushed. So while the code works, the unbuffered part doesn't – gimpycpu Apr 16 '14 at 3:29
  • I just fixed a typo in the stdbuf command. Other than that, there might be an additional issue with your editor not updating the file in a way that triggers tail. Can you try just appending to the file without the editor. For example, run date >>logfile.log a couple times in one window and see if awk, running in another window, prints the updates. – John1024 Apr 16 '14 at 3:52
  • Yes I did tried echo "My long string here" >> logfile.log from a different putty window. When I execute that line about 10 times the awk command will execute. – gimpycpu Apr 16 '14 at 3:59
  • @gimpycpu Using nano, I got various results depending on how I edited the file before saving. Using echo "My long string here" >> logfile.log, however, it works every time for me. – John1024 Apr 16 '14 at 4:00
5

I think @John1024's answer is not quite correct, as the stdbuf -o0 prefix is misplaced. It belongs as the prefix to the awk command, not the tail -f command, so the correct command should be:

tail -f logfile.log | stdbuf -o0 awk -F" " '{print $1, $2, $7, $8}'

Also note that not all versions of awk will function in that particular configuration. IOW, if you need that particular command string to function as written, keep trying various awk/gawk/mawk versions until you hit one that works.

  • I used the comment link to do that, but it prevented me due to not enough reputation. What means should I have used? – kenneth558 Sep 13 '16 at 0:04
  • Suggest the change to the post to which you had the suggestion ('improve this answer' option). Even anonymous users can do that. – kenorb Sep 13 '16 at 1:09
2

You could un-buffer it by adding a while loop as given in the example below. I have tested this on a running log file and it worked for me.

tail -f input.log | while read a; do echo "$a" | awk -F" " '{print $1, $2, $7, $8}' >> output.log; done
  • You generally want to avoid piping into while read if you can . If you can't, putting the awk pipe after the done would somewhat improve performance. But anyway, the proper fix is to disable buffering, not work around it. – tripleee Aug 16 '17 at 9:21
  • This helped me view log messages on an embedded system that lacked unbuffer and stdbuf – user275717 Aug 9 '18 at 23:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.