不打印通过两个命令
运行此:不打印通过两个命令
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