【问题标题】:Writing to both stdout & a file写入标准输出和文件
【发布时间】:2011-04-09 07:57:45
【问题描述】:

我有一个父进程,它派出一个子进程来执行 execv()。

我需要将 execv() 给 stdout 的输出显示在屏幕上,并将其复制到日志文件中。

如何将相同的输出写入标准输出和文件,不使用管道或三通

【问题讨论】:

标签: c file stdout


【解决方案1】:

您可以完全在您的程序中执行此操作,但您仍需要使用由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 状态)。

【讨论】:

    【解决方案2】:

    像这样使用Tee

    ./myprog | tee outputfile
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 该链接提供了一个示例,其中标准输出被重定向到一个文件,然后重定向回正常的标准输出。海报是在寻找一种将普通打印语句写入两个标准输出和文件的方法。
      • @Byron - 叉子不是为了打印目的,只是脚本逻辑的一部分,有一个例子。同一线程下的帖子具有纯逻辑,没有forklinuxforums.org/forum/linux-programming-scripting/…
      • 正如 a'r 所说,这并不能回答写入 both 标准输出和文件的原始问题。
      【解决方案4】:

      此外,您还可以使用 fifo。 mkfifo my.fifo; 在 execv 中:程序 > my.fifo; 并将 fifo 作为常规文件打开,从中读取。这样你就可以解析你的标准输出,但它在共享访问方面有一些小缺点。

      【讨论】:

        【解决方案5】:

        您是否只想将孩子的输出写入日志?

        tee unix command 完全符合您的描述:您通过管道输入数据并将其写入日志和标准输出。

        【讨论】:

          【解决方案6】:

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

          您应该编写一个日志记录函数来执行此操作以使其更清洁。

          【讨论】:

            【解决方案7】:

            通过tee 传递。

            【讨论】:

            • 有没有办法不用管道或三通,只使用 dup() 系列?
            猜你喜欢
            • 2012-06-04
            • 2018-12-07
            • 1970-01-01
            • 1970-01-01
            • 2013-03-18
            • 1970-01-01
            • 1970-01-01
            • 2019-09-01
            • 1970-01-01
            相关资源
            最近更新 更多