Как выполнить команду и получить вывод команды в C ++, используя POSIX?

добавить атрибут cursor:pointer;, чтобы добавить указатель, когда мышь наводится (вход не всегда имеет)

и, наконец, использовать line-height:46px; для вертикального выравнивания

полный код здесь -> http://jsbin.com/ecitex/10/edit

412
задан Peter Mortensen 5 January 2019 в 15:50
поделиться

4 ответа

#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>

std::string exec(const char* cmd) {
    std::array<char, 128> buffer;
    std::string result;
    std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
    if (!pipe) {
        throw std::runtime_error("popen() failed!");
    }
    while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
        result += buffer.data();
    }
    return result;
}

предC++ 11 версий:

#include <iostream>
#include <stdexcept>
#include <stdio.h>
#include <string>

std::string exec(const char* cmd) {
    char buffer[128];
    std::string result = "";
    FILE* pipe = popen(cmd, "r");
    if (!pipe) throw std::runtime_error("popen() failed!");
    try {
        while (fgets(buffer, sizeof buffer, pipe) != NULL) {
            result += buffer;
        }
    } catch (...) {
        pclose(pipe);
        throw;
    }
    pclose(pipe);
    return result;
}

Замена popen и pclose с _popen и _pclose для Windows.

553
ответ дан gregpaton08 24 September 2019 в 21:17
поделиться
  • 1
    Хорошо... интересные взгляды. Таким образом, как это работает? (Я don' t имеют подсказку Python), – Gunther Piez 28 November 2009 в 09:34

Я использовал бы popen () (++ waqas) .

, Но иногда Вам нужны чтение и запись...

кажется, что никто не делает вещи твердый путь больше.

(Принятие среды Unix/Linux/Mac или возможно Windows со слоем совместимости POSIX...)

enum PIPE_FILE_DESCRIPTERS
{
  READ_FD  = 0,
  WRITE_FD = 1
};

enum CONSTANTS
{
  BUFFER_SIZE = 100
};

int
main()
{
  int       parentToChild[2];
  int       childToParent[2];
  pid_t     pid;
  string    dataReadFromChild;
  char      buffer[BUFFER_SIZE + 1];
  ssize_t   readResult;
  int       status;

  ASSERT_IS(0, pipe(parentToChild));
  ASSERT_IS(0, pipe(childToParent));

  switch (pid = fork())
  {
    case -1:
      FAIL("Fork failed");
      exit(-1);

    case 0: /* Child */
      ASSERT_NOT(-1, dup2(parentToChild[READ_FD], STDIN_FILENO));
      ASSERT_NOT(-1, dup2(childToParent[WRITE_FD], STDOUT_FILENO));
      ASSERT_NOT(-1, dup2(childToParent[WRITE_FD], STDERR_FILENO));
      ASSERT_IS(0, close(parentToChild [WRITE_FD]));
      ASSERT_IS(0, close(childToParent [READ_FD]));

      /*     file, arg0, arg1,  arg2 */
      execlp("ls", "ls", "-al", "--color");

      FAIL("This line should never be reached!!!");
      exit(-1);

    default: /* Parent */
      cout << "Child " << pid << " process running..." << endl;

      ASSERT_IS(0, close(parentToChild [READ_FD]));
      ASSERT_IS(0, close(childToParent [WRITE_FD]));

      while (true)
      {
        switch (readResult = read(childToParent[READ_FD],
                                  buffer, BUFFER_SIZE))
        {
          case 0: /* End-of-File, or non-blocking read. */
            cout << "End of file reached..."         << endl
                 << "Data received was ("
                 << dataReadFromChild.size() << "): " << endl
                 << dataReadFromChild                << endl;

            ASSERT_IS(pid, waitpid(pid, & status, 0));

            cout << endl
                 << "Child exit staus is:  " << WEXITSTATUS(status) << endl
                 << endl;

            exit(0);


          case -1:
            if ((errno == EINTR) || (errno == EAGAIN))
            {
              errno = 0;
              break;
            }
            else
            {
              FAIL("read() failed");
              exit(-1);
            }

          default:
            dataReadFromChild . append(buffer, readResult);
            break;
        }
      } /* while (true) */
  } /* switch (pid = fork())*/
}
<час>

Вы также могли бы хотеть играть вокруг с выбором () и неблокирующиеся чтения.

fd_set          readfds;
struct timeval  timeout;

timeout.tv_sec  = 0;    /* Seconds */
timeout.tv_usec = 1000; /* Microseconds */

FD_ZERO(&readfds);
FD_SET(childToParent[READ_FD], &readfds);

switch (select (1 + childToParent[READ_FD], &readfds, (fd_set*)NULL, (fd_set*)NULL, & timeout))
{
  case 0: /* Timeout expired */
    break;

  case -1:
    if ((errno == EINTR) || (errno == EAGAIN))
    {
      errno = 0;
      break;
    }
    else
    {
      FAIL("Select() Failed");
      exit(-1);
    }

  case 1:  /* We have input */
    readResult = read(childToParent[READ_FD], buffer, BUFFER_SIZE);
    // However you want to handle it...
    break;

  default:
    FAIL("How did we see input on more than one file descriptor?");
    exit(-1);
}
33
ответ дан Peter Mortensen 24 September 2019 в 21:17
поделиться

Два возможных подхода:

  1. я не думаю popen(), часть стандарта C++ (это - часть POSIX из памяти), но это доступно на каждом UNIX, я работал с (и Вы, кажется, нацелены на UNIX, так как Ваша команда ./some_command).

  2. На всякий случай, что нет никакого popen(), можно использовать system("./some_command >/tmp/some_command.out");, затем использовать нормальные функции ввода-вывода для обработки выходного файла.

15
ответ дан paxdiablo 24 September 2019 в 21:17
поделиться

Можно использовать эти Повышение. Библиотека Process . Это не официально часть Повышения все же. Я видел, что он работает приятно на других. К сожалению, boost.process прогресс, по-видимому, был остановлен. pstreams является другим (по-видимому активным) проектом. Конечно, стоящий попытки я сказал бы - но это только для совместимых операционных систем POSIX.

14
ответ дан Peter Mortensen 24 September 2019 в 21:17
поделиться
  • 1
    @LiraNuna: первая версия была полная программа, но я обновил ее к новой версии так или иначе. – gnovice 28 November 2009 в 02:19
Другие вопросы по тегам:

Похожие вопросы: