Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

grep with continuous pipe does not work

(maybe it is the "tcpflow" problem)

I write a script to monitoring http traffic, and I install tcpflow, then grep

it works (and you should make a http request, for example curl www.163.com)

sudo tcpflow -p -c -i eth0 port 80 2>/dev/null | grep '^Host: '

it outputs like this (continuously)

Host: config.getsync.com
Host: i.stack.imgur.com
Host: www.gravatar.com
Host: www.gravatar.com

but I can't continue to use pipe

does not work (nothing output)

sudo tcpflow -p -c -i eth0 port 80 2>/dev/null | grep '^Host: ' | cut -b 7- 

does not work (nothing output)

sudo tcpflow -p -c -i eth0 port 80 2>/dev/null | grep '^Host: ' | grep H

When I replace sudo tcpflow with cat foo.txt, it works:

cat foo.txt | grep '^Host: ' | grep H

so what's wrong with pipe or grep or tcpflow ?


update:

This is my final script: https://github.com/zhengkai/config/blob/master/script/monitor_outgoing_http.sh

like image 405
Zheng Kai Avatar asked Feb 10 '17 11:02

Zheng Kai


People also ask

How does the grep command work in Unix?

Grep and most Unix commands operate on streams one line at a time. Each line that comes out of tail will be analyzed and passed on if it matches. Show activity on this post.

What is the difference between Grep and filter in Linux?

Pipes '|' send the output of one command as input of another command. The Filter takes input from one command, does some processing, and gives output. The grep command can be used to find strings and values in a text document. Piping through grep has to be one of the most common uses.

Is it possible to grep multiple lines at once?

Yes, this will actually work just fine. Grep and most Unix commands operate on streams one line at a time. Each line that comes out of tail will be analyzed and passed on if it matches.

How do I use multiple GREPS on a log file?

If you need to use multiple greps on a running log file and you find that you get no output, you may need to stick the --line-buffered switch into your middle grep (s), like so: tail -f /var/log/some.log | grep --line-buffered foo | grep bar


2 Answers

To grep a continuous stream use --line-buffered option:

sudo tcpflow -p -c -i eth0 port 80 2> /dev/null | grep --line-buffered '^Host'

--line-buffered

Use line buffering on output. This can cause a performance penalty.


Some reflections about buffered outputting(stdbuf tool is also mentioned):

Pipes, how do data flow in a pipeline?

like image 79
RomanPerekhrest Avatar answered Oct 23 '22 16:10

RomanPerekhrest


I think the problem is because of stdio buffering, you need to use GNU stdbuf before calling grep,

sudo tcpflow -p -c -i eth0 port 80 2>/dev/null | stdbuf -o0 grep '^Host: '

With the -o0, it basically means the output (stdout) stream from tcpflow will be unbuffered. The default behavior will be to automatically buffer up data into 40961 byte chunks before sending to next command in pipeline, which is what overriden using stdbuf


1. Refer this nice detail into the subject.

like image 10
Inian Avatar answered Oct 23 '22 16:10

Inian