重复调用 shell 命令,通过管道捕获标准输出

Repeat calls to shell command, capture stdout via pipe

本文关键字:管道 标准输出 调用 shell 命令      更新时间:2023-10-16

我正在尝试在Linux上获取C++应用程序,以定期检查蓝牙设备是否存在。 - 我可以通过命令行上的hcitool轻松完成此操作,并且它运行可靠。 - 如果我不理会 stdout,我可以在我的应用程序中多次执行此操作,并且它可以工作。 - 我可以将标准输出放入我的应用程序中,但它似乎与 hcitool 的输出不同步。

这是我到目前为止写的:

std::string checkBluetoothPresence(std::string searchForMAC)
{
    int pipeOut[2];
    pid_t pid;
    char btRtnVal[255] = "";
    pipe2(pipeOut, O_CLOEXEC);      // Both threads will share a pipe - input from child, output to parent
    switch(pid=fork())
    {
    case -1:    cout << "fork failed" << endl;
                exit(-1);
    case 0:     // Child thread
                close(1);               // Close stdout
                close(pipeOut[0]);      // Close the output end of pipeOut
                dup2(pipeOut[1], 1);    // Redirect stdout to pipeOut input
                close(pipeOut[1]);
                execl("/usr/bin/hcitool", "hcitool", "name", searchForMAC.c_str(), (char*)NULL);
    default:    // Parent thread
                close(0);               // Close stdin
                close(pipeOut[1]);      // Close the input to pipeOut
                dup2(pipeOut[0], 0);    // Redirect stdin to the pipeOut output
                close(pipeOut[0]);
                waitpid(pid, NULL, 0);
                cin.getline(btRtnVal, sizeof(btRtnVal)-1);
    }
    return btRtnVal;
}

基本上,就目前而言,如果检测到蓝牙设备,它将正确获取我的蓝牙设备的名称,并将其返回。 这将连续多次工作(我的 main(( 函数每 15 秒调用一次(。 如果我随后关闭设备上的蓝牙,它会返回一个空字符串(这就是我想要的(。 但是在那之后,如果我再次打开蓝牙,它就再也不起作用了。 它应该检测到它 - 它在命令行上工作,但不能在这里。 我已经尝试过删除所有管道/dup2/close命令,并且它运行良好(通过标准输出(。 所以我假设我的问题出在某处的管道/dup2/关闭命令上。 我已经尝试了很多变化(这只是最新的(,但无法让它工作。

我怀疑这与 stdout 的重定向未在某处正确重置有关,但我已经阅读并尝试了我在网上找到的数十种组合,但无法获得任何一种工作。 任何建议将不胜感激 - 这已经让我发疯了几个小时!

也许基本问题是:有没有人有一个好的、全面的示例来重定向 shell 命令的输出,读取它,然后重置所有内容,以便几秒钟后当我调用相同的命令时它仍然有效?

现在回答了 - 问题正如 Mats Petersson 在评论中指出的那样,我只是在父线程中缺少一个 cin.clear((。 一旦第一个失败,就会提出 EOF 标志,我想我认为下次创建线程时会自动重置该标志。