当第一个程序未在 BASH 中退出时使用 2 级管道的问题

Par*_*avi 6 linux bash pipe

考虑一下:

xinput  --test 11 | grep "button press   1"
Run Code Online (Sandbox Code Playgroud)

* 11是我的光电鼠标索引(可以是其他任何东西),“button press 1”表示左键单击。

当我点击屏幕上的某个地方时,会显示:

button press   1
Run Code Online (Sandbox Code Playgroud)

到目前为止没有问题。但是当我想使用它的输出作为我的 C 程序的输入时,我注意到在另一层管道之后程序的标准输入总是空的:

xinput  --test 11 | grep "button press   1" | ./poll_test
Run Code Online (Sandbox Code Playgroud)

这是我的poll_test代码:

xinput  --test 11 | grep "button press   1"
Run Code Online (Sandbox Code Playgroud)

尽管有点击,它什么也不打印。

这令人困惑。这不是正常行为。例如,当我运行它时:

ls | grep a | grep b
Run Code Online (Sandbox Code Playgroud)

它成功地向我展示了结果。唯一的区别是lshere 在打印到标准输出后退出,但在xinput版本中并非如此。

我花了很多时间编写一个脚本来在单击鼠标时发出哔哔声,但没有奏效。所以我想使用 C 程序,因为bash 中没有轮询功能。

据我所知,bash 中的管道工作是这样的:

第二个程序(管道语句中的正确程序)被执行,直到它想要从它的stdin读取并且它停止继续前进,直到有一些东西可以从STDIN读取。

考虑到这一点,我发布的命令中的第三个程序应该能够读取输出。第一个程序退出时就是这种情况。

如果管道问题不起作用,下一步将是直接使用libxcb而不是命令xinput

我完全糊涂了。任何帮助将非常感激。


编辑:我也尝试使用中间文件描述符:

exec 3<&1
xinput --test 11 | grep -i "button press   1" >&3  | ./poll_test 3>&1
Run Code Online (Sandbox Code Playgroud)

但没有帮助。而且强行刷新标准输出也不起作用:

xinput --test 11 | grep -i "button press   1" ; stdbuf -oL  | ./poll_test
Run Code Online (Sandbox Code Playgroud)