将stdout和stderr重定向到单个文件并保留消息顺序

时间:2017-07-10 07:57:21

标签: c linux io-redirection

我尝试将stdoutstderr重定向到带有C程序的单个文件。

这是我的代码:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int redirectOutputs();

int main()
{
    redirectOutputs();
    printf("OUT : test\n");
    perror("ERR : test");
    printf("OUT : test 2\n");


    int t = 23;
    printf("OUT : again\n");
    perror("ERR : again");

}

int redirectOutputs()
{
    int log = open("err.log", O_RDWR|O_CREAT|O_APPEND, 0600);
    if (log == -1)
    {
        perror("opening err.log");
        return -1;
    }
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
    dup2(log, STDOUT_FILENO);
    dup2(log, STDERR_FILENO);
    close(log);
}

输出文件:

ERR : test: Success
ERR : again: Success
OUT : test
OUT : test 2
OUT : again

它们都被重定向得很好,但似乎全部stderr被写入,然后是全部stdout。 我想保留文件中的消息顺序。 我应该有以下文件:

OUT : test
ERR : test: Success
OUT : test 2
OUT : again
ERR : again: Success

你知道我的代码中有什么问题吗?

2 个答案:

答案 0 :(得分:4)

问题是stdout的输出是缓冲,而stderr 无缓冲

您必须使stdout无缓冲,例如stderr,或将stderr缓存为stdout。您可以使用setvbuf设置缓冲和模式。

每次输出后,您也可以在stdout上致电fflush

答案 1 :(得分:3)

您的问题是缓冲。最简单的解决方案是在每次输出后调用fflush()。您当然可以使用setvbuf()将缓冲设置为行缓冲

也就是说,拥有一个显式日志记录界面可能更好一点,它也可以选择性地捕获stderrstdout。最后一句话,您的部分close()来电是多余的,dup2()会在复制之前自动关闭新的fd。