写给stdout&一份文件

时间:2010-09-07 17:26:57

标签: c file stdout

我有一个父进程,它会让一个孩子执行execv()。

我需要execv()给出的输出到stdout才能显示在屏幕上,同样也会复制到日志文件中。

如何将相同的输出写入stdout和amp;一个文件,不使用管道或T恤

7 个答案:

答案 0 :(得分:4)

如果您不想使用T恤,在写入数据之前,请将其写入文件,然后将其发送到stdout。

你应该编写一个记录功能,为你做这个以使它更清洁。

答案 1 :(得分:2)

通过tee管道。

答案 2 :(得分:2)

您可以使用dup2() - this link provides an example

答案 3 :(得分:2)

您可以在程序中完全执行此操作,但仍需要使用pipe()系统调用创建的匿名管道。

基本上,您需要一个执行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(),因为它们从父进程继承了标准I / O状态。

答案 4 :(得分:1)

另外,你可以使用fifo's。 mkfifo my.fifo; 在execv:program&gt; my.fifo; 并打开fifo作为常规文件,从中读取。通过这种方式,您可以对stdout进行解析,但共享访问存在轻微缺陷。

答案 5 :(得分:0)

您是否只想将孩子的输出转到日志?

tee unix command完全按照您的描述进行操作:管道输入数据并将其写入日志和标准输出。

答案 6 :(得分:0)

像这样使用Tee

./myprog | tee outputfile