使用连续管道的grep命令无法工作

6

也许这是“tcpflow”问题

我编写了一个脚本来监控http流量,并安装了tcpflow,然后使用grep

可以工作(你应该发起一个http请求,例如curl www.163.com

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

它的输出结果如下(持续不断地):
Host: config.getsync.com
Host: i.stack.imgur.com
Host: www.gravatar.com
Host: www.gravatar.com

但我不能继续使用管道

无效(没有输出任何内容)

sudo tcpflow -p -c -i eth0 port 80 2>/dev/null | grep '^Host: ' | cut -b 7- 
无法工作(没有任何输出)。
sudo tcpflow -p -c -i eth0 port 80 2>/dev/null | grep '^Host: ' | grep H

当我将 sudo tcpflow 替换为 cat foo.txt 时,它可以正常工作:

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

那么,管道、grep或tcpflow有什么问题吗?


更新:

这是我的最终脚本:https://github.com/zhengkai/config/blob/master/script/monitor_outgoing_http.sh


@Inian,现在我把它添加到问题中。 - Zheng Kai
它是如何失败的?没有输出吗? - Tom Zych
@ZhengKai:这是一个持续增长的数据流吗? - Inian
是的,无输出,并且应该是连续输出。 - Zheng Kai
1
@linuxfan不起作用ToT - Zheng Kai
显示剩余3条评论
2个回答

11

要对连续流进行grep,请使用--line-buffered选项:

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

--line-buffered

使用行缓冲输出。这可能会导致性能损失。


关于缓冲输出的一些思考(还提到了stdbuf工具):

管道,数据在管道中如何流动?


1
好的建议。在这种情况下,解释一下这个操作的作用和为什么会有所不同可能会很有用。 - Fred

10

我认为问题是由于stdio缓冲,在调用grep之前需要使用GNU stdbuf

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

使用-o0参数,它基本上意味着来自tcpflow的输出(stdout)流将不带缓冲。默认行为是将数据自动缓冲成4096字节块,然后发送到管道中的下一个命令,这是使用stdbuf覆盖的。


1. 可以参考这篇详细解释


3
在这种情况下,使用行缓冲(-oL)与默认缓冲一样好(因为grep总是操作整行),而且应该会更快一些(尽管在这种特定情况下性能实际上可能并不重要)。 - Fred

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接