【问题标题】:Problem using 2-level pipe when the first program doesn't exit in BASH当第一个程序未在 BASH 中退出时使用 2 级管道出现问题
【发布时间】:2020-06-21 19:52:47
【问题描述】:

考虑一下:

xinput  --test 11 | grep "button press   1"

*11 是我的光学鼠标索引(可以是其他任何值),"button press 1" 表示左键单击。

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

button press   1

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

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 在打印到 stdout 后退出,但在 xinput 版本中并非如此。

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

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

第二个程序(管道语句中的正确程序)被执行,直到它想要从它的 stdinREAD 并且它停止进一步直到有东西可以读取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

【问题讨论】:

    标签: linux bash pipe


    【解决方案1】:

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

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

    【讨论】:

    • 如果您使用其他grep,也可以使用stdbuf
    猜你喜欢
    • 2016-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-23
    • 2011-09-29
    • 1970-01-01
    • 2010-12-07
    • 2014-06-04
    相关资源
    最近更新 更多