为什么输出管道通过grep出现在块中而不是逐行出现?

时间:2016-06-22 07:33:16

标签: pipe sh

我的命令行有很大的性能问题。如果我输入:

hcidump -a

我得到以下输出:

> HCI Event: LE Meta Event (0x3e) plen 42
    LE Advertising Report
      ADV_IND - Connectable undirected advertising (0)
      bdaddr 78:A5:04:17:9F:66 (Public)
      Flags: 0x06
      Unknown type 0xff with 25 bytes data
      RSSI: -26
> HCI Event: LE Meta Event (0x3e) plen 41
    LE Advertising Report
      SCAN_RSP - Scan Response (4)
      bdaddr 78:A5:04:17:9F:66 (Public)
      Complete local name: 'BEACON 17:9F:66'
      TX power level: 0
      Unknown type 0x16 with 7 bytes data
      RSSI: -26

每一块信息都会在屏幕上实时显示。但由于我只需要RSSI的值,我使用此命令来获取它:

hcidump -a | egrep 'RSSI|bdaddr' | grep -A1 --no-group-separator 'bdaddr 78:A5:04:17:9F:66' | grep -Po 'RSSI:\s+\K.*'

它完美无缺,但我有很大的性能问题。由于两位数值不是在屏幕上逐个显示,而是以块为单位。 12-15秒没有发生任何事情,然后我一次得到40个值。有什么机构知道问题是什么吗?

pipe-command是否使用缓冲区? 或者有人知道如何缩短命令,如上所示?提高性能?

最好的问候阿德里安

1 个答案:

答案 0 :(得分:3)

性能问题是由grep命令检测到它们的输出不是终端设备,因此在打印输出时使用块缓冲。如果你正在使用GNU grep,你可以使用它的--line-buffered缓冲区而不是 block 的数据。

如果您只需要RSSI值,则可以使用一个grep命令替换管道sed命令:

hcidump -a | sed -n 's/[ \t]*RSSI: //p'

-n选项告诉sed 打印每一行。它在每一行中搜索前面有任意数量的空白字符的字符串RSSI:,并用空字符串替换整个批次。最终p指示sed在替换完成后打印该行。

由于sed命令直接打印到终端设备,因此不应阻止缓冲区输出。如果您希望将其打印到终端以外的其他内容并使用GNU sed,则可以使用其-u, --unbuffered选项

  

从输入文件加载最少量的数据并更频繁地刷新输出缓冲区

I / O缓冲的一般信息

当程序将文本打印到输出流时,打印将被缓冲。 有两种类型:

  • 线路缓冲表示每当遇到换行时都会写输出。
  • 阻止缓存表示之前等待一定数量的数据 写作。数量取决于内核配置; 4096字节是 Linux的默认值。

标准流

  • stdin始终是块缓冲的。
  • stderr是行缓冲的。
  • stdout取决于输出设备:
    • 如果线路缓冲连接到终端设备,则使用线路缓冲
    • 如果不是(例如,stdout连接,则使用块缓冲 管道中另一个程序的stdin

有用的链接

Grep and Output Buffering提供 对这个问题的正确介绍。

PádraigBrady写了一篇很好的文章来解释内核发生了什么 级别:buffering in standard streams

Jonathon Perkin解释了如何为许多程序解决此问题: How to fix stdio buffering

这个Unix& Linux Stack Exchange问​​题涵盖了许多解决方案: Turn off buffering in pipe