不打印通过两个命令

运行此:不打印通过两个命令

ping google.com | grep -o 'PING' 

将打印PING到终端,所以我假定意味着grep的的标准输出由终端捕获。

那么为什么不按照下面的命令打印什么?终端只是挂:

ping google.com | grep -o 'PING' | grep -o 'IN' 

我认为,第一grep命令的标准输出将被重定向到第二的grep的标准输入。然后第二个grep的标准输出将被终端捕获并打印。

这似乎是,如果平被替换回声会发生什么:

echo 'PING' | grep -o 'PING' | grep -o 'IN' 

IN被打印到终端,如我期望的那样。

那么ping有什么特别之处,可以防止打印任何东西?

回答:

你可以尝试更加耐心:-)

ping google.com | grep -o 'PING' | grep -o 'IN' 

最终显示输出,但它可能需要一个半小时左右。

在Unix下,如果流是终端,则在启动时交给程序的标准输出流是“行缓冲”的;否则它会被完全缓冲,通常使用8千字节(8,192个字符)的缓冲区。缓冲意味着输出在内存中累积,直到缓冲区已满,或者在线路缓冲流的情况下,直到发送换行符为止。

当然,程序可以覆盖此设置,只生成少量输出的程序(如ping)通常会执行stdout行缓冲,而不管它是什么。但grep不这样做(虽然你可以告诉牛羚grep来做到这一点通过--line-buffered命令行选项。)

“管道”(其中创建实现|运营商)都没有考虑终端。因此中间的grep将具有完全缓冲输出,这意味着其输出将被缓冲直到写入8k个字符。这将需要一段时间,因为每行只包含5个字符(PING加换行符),并且它们每秒生成一次。所以缓冲区将在大约1640秒后填满,这大约是28分钟。

很多unix发行版带有一个名为stdbuf的程序,它可以用来在运行程序之前更改标准流的缓冲区。 (如果你有stdbuf,你可以通过输入man 1 stdbuf来了解它是如何工作的。)像Perl这样的编程语言通常提供其他机制来调用标准库函数stdbuf。 (在Perl中,可以在每次写入后使用内置变量$|autoflush(BOOL) io handle方法强制刷新。)

当然,当程序成功终止时,所有输出缓冲区都会“刷新”(srnt)各自的流)。所以

echo PING | grep -o 'PING' | grep -o 'IN' 

将立即输出其唯一的输出行。但是,除非您提供了计数命令行选项(-c N;请参阅man ping),否则ping不会终止。因此,如果您需要立即管道吞吐量,则可能需要修改缓冲行为。

以上是 不打印通过两个命令 的全部内容, 来源链接: utcz.com/qa/258276.html

回到顶部