C++ 如何捕获在C++中运行的命令的exit_code和stderr?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15058876/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:57:40  来源:igfitidea点击:

How to capture the exit_code and stderr of the command that is run in C++?

c++popenstderrexit-code

提问by Logan

I'm writing a c++ program that executes and outputs (in real-time) a shell script, makefile or just another program. However I would like to have my program return differently when there are errors or no error.

我正在编写一个 c++ 程序,它执行和输出(实时)shell 脚本、makefile 或只是另一个程序。但是,当有错误或没有错误时,我想让我的程序以不同的方式返回。

#include "execxi.h"



using namespace std;


int execXI::run(string command)
{

    FILE *in;
    char buff[512];
    // is this the check for command execution exited with not 0?
    if(!(in = popen(command.c_str(), "r"))){
            // I want to return the exit code and error message too if any
        return 1;
    }
    // this part echoes the output of the command that's executed
    while(fgets(buff, sizeof(buff), in)!=NULL){
        cout << buff;
    }
    pclose(in);
    return 0;



}

is what I have so far.

是我到目前为止。

Let's say this script ran maketo build a program and it gave an error like so

假设这个脚本运行make来构建一个程序,它给出了这样的错误

on_target_webkit_version out/Release/obj/gen/webkit_version.h
Traceback (most recent call last):
  File "../build/webkit_version.py", line 107, in <module>
    sys.exit(main())
  File "../build/webkit_version.py", line 103, in main
    return EmitVersionHeader(*sys.argv[1:])
  File "../build/webkit_version.py", line 86, in EmitVersionHeader
    webkit_revision = GetWebKitRevision(webkit_dir, version_file)
  File "../build/webkit_version.py", line 60, in GetWebKitRevision
    version_info = lastchange.FetchVersionInfo(
AttributeError: 'module' object has no attribute 'FetchVersionInfo'
make: *** [out/Release/obj/gen/webkit_version.h] Error 1
  • Is it possible for me to know that this exited with error?

    • Does that exit with code else than 0since it is an error?

    • Is that last part outputted in stderr?

  • 我有可能知道这退出时有错误吗?

    • else than 0因为它是一个错误,所以它会以代码退出吗?

    • 最后一部分是在 中输出的stderr吗?

Considering that makeexited with code not 0, let's say 1, and it output in stderris it not possible for me to capture these exit codes and error message in the end?

考虑到make以代码 not 退出,0比方说1,它输出stderr是我最终无法捕获这些退出代码和错误消息吗?

How can I capture the exit code and stderrafter outputting the results of the program, and return the exit code/ stderrin the function?

如何捕获退出代码并stderr在输出程序结果后,并在函数中返回exit code/ stderr

采纳答案by lpapp

If you are interested in the error code, this is a more portable way of getting it rather than dividing by 256:

如果您对错误代码感兴趣,这是一种更便携的获取方式,而不是除以 256:

printf("Exit code: %i\n", WEXITSTATUS(pclose(fp)));

However, popenis one way, so you are either creating further workarounds by the usual redirection style in shell, or you follow this untested code to do it right:

但是,这popen是一种方法,因此您要么通过 shell 中通常的重定向样式创建进一步的解决方法,要么按照以下未经测试的代码正确执行此操作:

#include <unistd.h>
#include <stdio.h>

/* since pipes are unidirectional, we need two pipes.
   one for data to flow from parent's stdout to child's
   stdin and the other for child's stdout to flow to
   parent's stdin */

#define NUM_PIPES          2

#define PARENT_WRITE_PIPE  0
#define PARENT_READ_PIPE   1

int pipes[NUM_PIPES][2];

/* always in a pipe[], pipe[0] is for read and 
   pipe[1] is for write */
#define READ_FD  0
#define WRITE_FD 1

#define PARENT_READ_FD  ( pipes[PARENT_READ_PIPE][READ_FD]   )
#define PARENT_WRITE_FD ( pipes[PARENT_WRITE_PIPE][WRITE_FD] )

#define CHILD_READ_FD   ( pipes[PARENT_WRITE_PIPE][READ_FD]  )
#define CHILD_WRITE_FD  ( pipes[PARENT_READ_PIPE][WRITE_FD]  )

void
main()
{
    int outfd[2];
    int infd[2];

    // pipes for parent to write and read
    pipe(pipes[PARENT_READ_PIPE]);
    pipe(pipes[PARENT_WRITE_PIPE]);

    if(!fork()) {
        char *argv[]={ "/usr/bin/bc", "-q", 0};

        dup2(CHILD_READ_FD, STDIN_FILENO);
        dup2(CHILD_WRITE_FD, STDOUT_FILENO);

        /* Close fds not required by child. Also, we don't
           want the exec'ed program to know these existed */
        close(CHILD_READ_FD);
        close(CHILD_WRITE_FD);
        close(PARENT_READ_FD);
        close(PARENT_WRITE_FD);

        execv(argv[0], argv);
    } else {
        char buffer[100];
        int count;

        /* close fds not required by parent */       
        close(CHILD_READ_FD);
        close(CHILD_WRITE_FD);

        // Write to child's stdin
        write(PARENT_WRITE_FD, "2^32\n", 5);

        // Read from child's stdout
        count = read(PARENT_READ_FD, buffer, sizeof(buffer)-1);
        if (count >= 0) {
            buffer[count] = 0;
            printf("%s", buffer);
        } else {
            printf("IO Error\n");
        }
    }
}

The code is from here:

代码来自这里:

http://jineshkj.wordpress.com/2006/12/22/how-to-capture-stdin-stdout-and-stderr-of-child-program/

http://jineshkj.wordpress.com/2006/12/22/how-to-capture-stdin-stdout-and-stderr-of-child-program/

回答by Logan

The returnvalue of the child process is in the top 168 bits. You have to divide the returned value of pclose by 256, then you get the searched return value of the child process.

子进程的返回值在前16 个8 位。必须将pclose的返回值除以256,才能得到子进程的搜索返回值。

Gotten from http://bytes.com/topic/c/answers/131694-pclose-returning-termination-status-command

来自http://bytes.com/topic/c/answers/131694-pclose-returning-termination-status-command

My answer would be pclose(in)/256is exit code.

我的答案pclose(in)/256是退出代码。

I still don't know how to capture stderr or sdtout differently but until there's an answer for that I will accept this as my answer.

我仍然不知道如何以不同的方式捕获 stderr 或 sdtout 但直到有答案我才会接受这个作为我的答案。

回答by Wtower

Thanks for the reply about exit code Logan.

感谢您对退出代码 Logan 的回复。

I believe a round-trip to get stderr would be to redirect it to a temporary file:

我相信获取 stderr 的往返是将它重定向到一个临时文件:

FILE* f = popen("cmd 2>/tmp/tmpfile.txt", "r");