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

标签 linux bash pipe

考虑一下:

xinput  --test 11 | grep "button press   1"
* 11 是我的光电鼠标索引(可以是其他任何东西)和 “按下按钮 1” 表示左键单击。
当我点击屏幕上的某个地方时,会显示:
button press   1
到目前为止没有问题。但是当我想使用它的输出作为我的 C 程序的输入时,我注意到 标准输入 程序的另一层管道总是空的:
xinput  --test 11 | grep "button press   1" | ./poll_test
这是我的 poll_test 代码:
/*This is just a program to test polling functionality on stdin.
I've used other programs instead of this as well.
None of them were able to read the stdin */

#include <fcntl.h>
#include <stdio.h>
#include <sys/poll.h>
#include <sys/time.h>
#include <unistd.h>

void main(int argc, char ** argv) {
    int fd;
    char buf[1024];
    int bytes_read;
    struct pollfd pfds[1];

while (1) {
        pfds[0].fd = 0;
        pfds[0].events = POLLIN;
        poll(pfds, 1, -1);
        if (pfds[0].revents & POLLIN) {
            bytes_read = read(0, buf, 1024);
            printf("%s\n" , buf);
            if (!bytes_read) {
                printf("stdin closed\n");
                return;
            }
            write(1, buf, bytes_read);
        }
    }
}
尽管有点击,它什么也不打印。
这令人困惑。这不是正常行为。例如,当我运行它时:
ls | grep a | grep b
它成功地向我展示了结果。唯一的区别是ls这里在打印到 后退出标准输出 但在 中情况并非如此xinput 版本。
我花了很多时间编写一个脚本来在单击鼠标时发出哔哔声,但没有奏效。所以我想使用 C 程序,因为没有 投票 bash 中的功能。
据我所知,bash 中的管道工作是这样的:

The second program (the right one in the pipe statement) gets executed until it wants to READ from its stdin and it stops going further until there's something to read from the STDIN.


考虑到这一点,我发布的命令中的第三个程序应该能够读取输出。第一个程序退出时就是这种情况。
下一步是使用 libxcb 直接代替命令 xinput 如果管道问题不起作用。
我完全糊涂了。任何帮助将非常感激。

编辑:我还尝试使用中间文件描述符:
exec 3<&1
xinput --test 11 | grep -i "button press   1" >&3  | ./poll_test 3>&1
但没有帮助。而且强行刷新标准输出也不起作用:
xinput --test 11 | grep -i "button press   1" ; stdbuf -oL  | ./poll_test

最佳答案

好像grep正在根据输出是否为终端来改变其缓冲行为。我不知道为什么会发生这种情况,但是 --line-buffered强制它使用行缓冲(在行结束时立即评估表达式):

xinput --test 11 | grep "button press   1" --line-buffered | ./poll_test

关于linux - 当第一个程序未在 BASH 中退出时使用 2 级管道的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62503699/

相关文章:

Python 使用管道处理输入/输出

python - 使python程序在linux下独立可执行

bash - 如果命令在变量中,则在子 shell 中执行管道命令不起作用

linux - 用 !! 在 bash 脚本中开始一行! (双响)

linux - bash:如何仅传输/复制文件名以分隔相似的文件?

bash - {1} 在 |master {1} 中是什么意思 ✓|与 bashit?

bash - 如何临时切换 AWS CLI 的配置文件?

pipe - 如何根据同一仪器中先前的复选框结果自动填充 REDCap 复选框

c - 如何在 posix 线程之间发出缓冲区已满状态的信号

linux - { 处或附近的语法错误