как получить строку вывода команды linux и статус вывода в c++

Я хочу получить выходную строку команды Linux, а также статус вывода команды в программе на C++. Я выполняю команды Linux в своем приложении.

например: Команда:

rmdir abcd

строка вывода команды:

rmdir: не удалось удалить "abcd": нет такого файла или каталога

Командная Статус:

1 (Что означает команда была не удалось)

Я попытался использовать функцию Linux system() который дает состояние выхода, и функция popen() что дает мне строку вывода команды, но ни одна функция не дает мне строка вывода и состояние вывода команды Linux.

5 ответов


строка вывода находится в стандартном дескрипторе вывода или стандартной ошибки (1 или 2 соответственно).

вы должны перенаправить эти потоки (взгляните на dup и dup2 функция) в место, где вы можете их прочитать (например-POSIX pipe).

в C я бы сделал что-то вроде этого:

int pd[2];
int retValue;
char buffer[MAXBUF] = {0};
pipe(pd);
dup2(pd[1],1);
retValue = system("your command");
read(pd[0], buffer, MAXBUF);

теперь у вас есть (часть) вашего вывода в buffer и код возврата в retValue.

кроме того, вы можете использовать функцию из exec (т. е. execve) и получить возвращаемое значение с wait или waitpid.

Update: это перенаправит только стандартный вывод. Чтобы перенаправить стандартную ошибку, используйте dup2(pd[1],1).


самое простое решение-использовать system, и перенаправить стандартную и стандартную ошибку во временный файл, который вы можете удалить позже.


к сожалению, в C на Linux нет простого и простого способа сделать это. здесь пример правильного чтения/записи stdout/stderr/stdin дочернего процесса.

и когда вы хотите получить код выхода, вы должны использовать waitpid (полный пример приведен внизу страницы):

endID = waitpid(childID, &status, WNOHANG|WUNTRACED);

теперь вам просто нужно объединить эти два вместе:)

есть отличная бесплатная книга Advanced Linux Pпрограммирования (ALP), содержащий подробную информацию об этих видах проблем, доступных здесь.


основываясь на ответе Петра Зиерхоффера выше, вот функция, которая делает именно это, а также восстанавливает stdout и stderr их исходное состояние.

// Execute command <cmd>, put its output (stdout and stderr) in <output>,
// and return its status
int exec_command(string& cmd, string& output) {
    // Save original stdout and stderr to enable restoring
    int org_stdout = dup(1);
    int org_stderr = dup(2);

    int pd[2];
    pipe(pd);

    // Make the read-end of the pipe non blocking, so if the command being
    // executed has no output the read() call won't get stuck
    int flags = fcntl(pd[0], F_GETFL);
    flags |= O_NONBLOCK;

    if(fcntl(pd[0], F_SETFL, flags) == -1) {
        throw string("fcntl() failed");
    }

    // Redirect stdout and stderr to the write-end of the pipe
    dup2(pd[1], 1);
    dup2(pd[1], 2);
    int status = system(cmd.c_str());
    int buf_size = 1000;
    char buf[buf_size];

    // Read from read-end of the pipe
    long num_bytes = read(pd[0], buf, buf_size);

    if(num_bytes > 0) {
        output.clear();
        output.append(buf, num_bytes);
    }

    // Restore stdout and stderr and release the org* descriptors
    dup2(org_stdout, 1);
    dup2(org_stderr, 2);
    close(org_stdout);
    close(org_stderr);

    return status;
}

можно использовать popen системный вызов, он будет перенаправлять вывод в файл и из файла, вы можете перенаправить вывод в строку. например:

    char buffer[MAXBUF] = {0};
    FILE *fd = popen("openssl version -v", "r");
    if (NULL == fd)
    {
        printf("Error in popen");
        return;
    }
    fread(buffer, MAXBUF, 1, fd);
    printf("%s",buffer);

    pclose(fd);

подробнее man страница popen.