【问题标题】:How to capture output of strace in C++ program如何在 C++ 程序中捕获 strace 的输出
【发布时间】:2014-12-23 06:51:50
【问题描述】:

我想在我的 C++ 程序中分析 strace 的输出。从我的应用程序启动 /bin/strace ps 时,我从 ps 获得输出,但不是从 strace 获得输出,并且 strace 输出被打印到 stdout(我的终端)。我使用使用管道和重定向流的标准技术。

这是我的来源:

#include <stdlib.h> 
#include <iostream> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <fcntl.h>
int main(){
    char *const parmList[] = {"/bin/strace", "ps", NULL};
    int pipes[2];
    pipe(pipes);
    pid_t child = fork();
    if(child == 0){
        close(pipes[0]);
        dup2(pipes[1],1);
        execv(parmList[0], parmList);
    }
    else{
        int status;
        wait(&status);

        fcntl(pipes[0], F_SETFL, O_NONBLOCK | O_ASYNC); 
        char buf[128] = {0}; 
        ssize_t bytesRead; 
        std::string stdOutBuf; 
        while(1) {
            bytesRead = read(pipes[0], buf, sizeof(buf)-1);
            if (bytesRead <= 0)
                break;
            buf[bytesRead] = 0;
            stdOutBuf += buf;
        } 
        std::cout << "<stdout>\n" << stdOutBuf << "\n</stdout>" << std::endl; 
    }

    close(pipes[0]);
    close(pipes[1]);

    return 0;
 }

如何在我的程序中获得 strace 的输出?

【问题讨论】:

    标签: c++ linux strace execv


    【解决方案1】:

    strace 写入stderr 而不是stdout,如果您只想捕获 strace 输出,只需使用 stderr 而不是 stdout

    像这样更改dup2

         dup2(pipes[1],2);
    

    如果您想要组合 strace 和 ps 输出,请执行以下操作:

        dup2(pipes[1],1);
        dup2(pipes[1],2);
    

    如果你想要分离输出,你可能需要使用非阻塞读取和 select() 或 poll()

    另外:调用 exec 后你应该打印一条错误消息,如果一切正常,exec 不会返回,但如果 exec 出现问题,很高兴知道。

    std::cerr << "exec failed!";
    

    我使用了这段代码并且成功了:

    #include <stdlib.h> 
    #include <iostream> 
    #include <sys/types.h> 
    #include <sys/wait.h> 
    #include <unistd.h> 
    #include <fcntl.h>
    int main(){
        char *const parmList[] = {"/usr/bin/strace", "ps", NULL};
        int pipes[2];
        pipe(pipes);
        pid_t child = fork();
        if(child == 0){
            close(pipes[0]);
            dup2(pipes[1],2);
            execv(parmList[0], parmList);
              std::cerr << "exec fail\n" ;
        }
        else{               
            int status;
            wait(&status);
    
            fcntl(pipes[0], F_SETFL, O_NONBLOCK | O_ASYNC); 
            char buf[128] = {0}; 
            ssize_t bytesRead; 
            std::string stdOutBuf; 
            while(1) {
                bytesRead = read(pipes[0], buf, sizeof(buf)-1);
                if (bytesRead <= 0)
                    break;
                buf[bytesRead] = 0;
                stdOutBuf += buf;
            } 
            std::cout << "<stdout>\n" << stdOutBuf << "\n</stdout>" << std::endl; 
        }
        close(pipes[0]);
        close(pipes[1]);
    
        return 0;
    }
    

    HTH

    【讨论】:

    • 感谢您的回复,但如果我重定向 stderr 则它会完全挂起,即使父母所做的只是等待(&status)
    • 嗯,它应该可以工作。我无法编译你的源代码。
    • 奇怪,我用 g++ 4.9.1 编译它,由于不推荐的转换它给出了一些警告,但它编译了
    • 谢谢,由于某种原因,我试图使用 gcc :(。当它编译时,我发现我还必须将 strace 上的路径更改为 "/usr/bin/strace",然后它按预期工作。跨度>
    • 谢谢你的帮助,原来是在使用ps的时候才挂起……很奇怪,可能是我的archlinux特有的
    猜你喜欢
    • 1970-01-01
    • 2011-05-18
    • 1970-01-01
    • 2023-04-07
    • 2016-11-01
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多