У меня есть родительский процесс, который выдает дочерний элемент для выполнения execv ().
Мне нужен вывод, выданный execv (), на stdout, который будет отображаться на экране, также скопированный в файл журнала.
Как написать тот же вывод в файл stdout и файл, не используя трубы или тройники ?
Если вы не хотите использовать тройник, прежде чем писать данные, напишите его в файл, а затем отправьте его в стандартный вывод.
Вы должны написать функцию регистрации, которая сделает это для вас, чтобы сделать его более чистым.
Протрите его через тройник .
Вы можете использовать dup2()
– эта ссылка дает пример
Вы можете сделать это полностью в своей программе, но вам все равно придется использовать анонимные каналы, созданные системным вызовом pipe()
.
В принципе, вам понадобится subprocess, который выполняет эквивалент tee
, что довольно просто:
int child_pipe[2]; pid_t pid_exec_child, pid_output_child; pipe(child_pipe); pid_exec_child = fork(); if (pid_exec_child == 0) { dup2(child_pipe[1], STDOUT_FILENO); close(child_pipe[0]); close(child_pipe[1]); execve(/* ... */); _exit(127); } close(child_pipe[1]); pid_output_child = fork(); if (pid_output_child == 0) { /* This child just loops around, reading from the other child and writing everything * to both stdout and the log file. */ int logfd = open("logfile", O_WRONLY); char buffer[4096]; ssize_t nread; while ((nread = read(child_pipe[0], buffer, sizeof buffer) != 0) { size_t nwritten_total; ssize_t nwritten; if (nread < 0) { if (errno == EINTR) continue; perror("read"); _exit(1); } /* Copy data to stdout */ nwritten_total = 0; while (nwritten_total < nread) { nwritten = write(STDOUT_FILENO, buffer + nwritten_total, nread - nwritten_total); if (nwritten < 0) { if (errno == EINTR) continue; perror("write(stdout)"); _exit(2); } nwritten_total += nwritten; } /* Copy data to logfile */ nwritten_total = 0; while (nwritten_total < nread) { nwritten = write(logfd, buffer + nwritten_total, nread - nwritten_total); if (nwritten < 0) { if (errno == EINTR) continue; perror("write(logfile)"); _exit(3); } nwritten_total += nwritten; } } _exit(0); } close(child_pipe[0]); /* Parent continues here */
Конечно, проще всего просто запустить tee
у этого второго ребенка ...
(Обратите внимание, что дочерние процессы используют _exit()
, поскольку они унаследовали стандартное состояние ввода-вывода от родителя).
Кроме того, вы можете использовать fifo. mkfifo my.fifo; в execv: program> my.fifo; и откройте fifo как обычный файл, читая его. Таким образом, вы можете проанализировать ваш stdout, но он имеет небольшие недостатки с общим доступом.
Вы хотите, чтобы только выход дочернего элемента поступал в журнал?
Команда tee unix выполняет именно то, что вы описываете: вы обрабатываете данные и записываете в журнал и в стандартный вывод.
Используйте Tee следующим образом:
./myprog | tee outputfile