В настоящее время я разрабатываю кросс-платформенный проект. В windows у меня был класс, который запускал процесс/скрипт (используя командную строку), ждал его завершения и прочитал все из него stdout/stderr в буфер. Затем я распечатал вывод на пользовательскую консоль. Примечание. Это не было перенаправление дочернего stdout на родительский stdout, а только на канал от дочернего stdout до родителя.
Я новичок в OSX/unix-подобном api, но я понимаю, что канонический способ сделать что-то вроде этого - это разветвление и совместное использование stdouts. Тем не менее, я не хочу перенаправлять его на stdout, и я хотел бы захватить вывод. Он должен работать примерно так (псевдокод, сходство с функциями unix чисто совпадающее):
class program
{
string name, cmdline;
string output;
program(char * name, char * cmdline)
: name(name), cmdline(cmdline) {};
int run()
{
// run program - spawn it as a new process
int pid = exec(name, cmdline);
// wait for it to finish
wait(pid);
char buf[size];
int n;
// read output of program stdout
// keep appending data until there nothing left to read
while (read(pid, buf, size, &n))
output.append(buf, n);
// return exit code of process
return getexitcode(pid);
}
const string & getOutput() { return output; }
};
Как я буду делать это на OSX?
E:
Хорошо, поэтому я изучил соответствующий api, и кажется, что какая-то комбинация fork/exec неизбежна. Проблема в том, что мой процесс очень велик, и нарисовать его действительно кажется плохой идеей (я вижу, что некоторые реализации unix не могут этого сделать, если родительский процесс занимает 50% + системного бара).
Разве я не могу избежать этой схемы? Я вижу, что vfork() может быть потенциальным соперником, поэтому, возможно, я попытаюсь имитировать функцию popen() с помощью vfork. Но опять же, на большинстве страниц man указано, что vfork вполне может быть просто fork()
У вас есть вызов библиотеки, чтобы сделать это: popen. Он предоставит вам возвращаемое значение дескриптора файла, и вы сможете прочитать этот дескриптор до eof. Это часть stdio, поэтому вы можете сделать это на OSX, но и на других системах. Просто запомните pclose() дескриптор.
#include <stdio.h>
FILE * popen(const char *command, const char *mode);
int pclose(FILE *stream);
если вы хотите сохранить выход без переадресации, единственное, что мы можем подумать, это использовать что-то вроде "tee" - команды, которая разбивает вывод на файл, но сохраняет свой собственный stdout. Это довольно легко реализовать и в коде, но в этом случае это может и не понадобиться.