как получить строку вывода команды 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
.