重复调用shell命令,通过管道捕获stdout

时间:2014-12-07 11:54:46

标签: c++ pipe exec fork dup2

我试图在Linux上获得一个C ++应用程序来定期检查是否存在蓝牙设备。   - 我可以通过命令行上的hcitool轻松完成这项工作,并且可以正常工作。   - 我可以在我的应用程序中多次执行此操作,如果我单独使用stdout,它可以正常工作。   - 我可以将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秒调用一次)。如果我在我的设备上关闭蓝牙,它会返回一个空字符串(这就是我想要的)。在那之后,如果我再次打开蓝牙,它再也不会工作了。它应该检测它 - 它在命令行上工作,但不在这里。我已经尝试删除了所有的pipe / dup2 / close命令,并且它完美地工作(通过stdout)。所以我认为我的问题在于我的pipe / dup2 / close命令。我尝试了很多变化(这只是最新版本),但无法让它发挥作用。

我怀疑这与某些地方没有正确重置的stdout的重定向有关,但我已经阅读并尝试过我在网上找到的几十种组合,但无法获得任何工作。任何建议都会非常感激 - 这让我疯了几个小时!

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

1 个答案:

答案 0 :(得分:0)

现在回答 - 问题是Mats Petersson在评论中指出的,我只是在父线程中错过了一个cin.clear()。一旦第一个失败,EOF标志就会被提升,我想我下次在下次创建线程时会自动重置。