简体   繁体   English

使用dup2将stdout / stderr重定向到同一文件时出现问题

[英]Trouble using dup2 to redirect stdout/stderr into the same file

I'm having some trouble using dup2 in trying to redirect both stdout and stderr into the same output file. 使用dup2尝试将stdoutstderr都重定向到同一输出文件时遇到了一些麻烦。

I'm using this explanatory code sample: (gcc 4.8.2, Ubuntu 14.04) 我正在使用此说明性代码示例:(gcc 4.8.2,Ubuntu 14.04)

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

#define USE2FILES

int main()
{
    int f1, f2, status;

    f1 = open("test.out", O_CREAT | O_WRONLY, 0644);
    if (f1 == -1) {
        perror("open(): ");
    }
    status = dup2(f1, STDOUT_FILENO);
    if (status == -1) {
        perror("dup2(): ");
    }

#ifdef USE2FILES
    close(f1);
#endif

#ifdef USE2FILES
    f2 = open("test.out", O_CREAT | O_WRONLY, 0644);
    if (f2 == -1) {
        perror("dup2(): ");
    }
#else
    f2 = f1;
#endif
    status = dup2(f2, STDERR_FILENO);
    if (status == -1) {
        perror("dup2(): ");
    }
    close(f2);

    fprintf(stderr, "test_stderr1\n");
    fprintf(stdout, "test_stdout1\n");
    fprintf(stderr, "test_stderr2\n");
    fprintf(stdout, "test_stdout2\n");
    fprintf(stderr, "test_stderr3\n");
    fprintf(stdout, "test_stdout3\n");

    fflush(stdout);
    fflush(stderr);

    return 0;
}

USE2FILES macro is supposed to switch between using either 2 file descriptors (to the same file) which get duped to stdout and stderr respectivly or 1 file descriptor which gets duplicated both to stdout and stderr . USE2FILES宏应该使用哪个上当受骗要么2个文件描述符(到相同的文件中)之间进行切换stdoutstderr respectivly或它获取复制既1个文件描述符stdoutstderr

I was under the impression that using 2 distinct file descriptors for redirection should work. 我的印象是,使用2个不同的文件描述符进行重定向应该可以工作。 However running this piece of code with USE2FILES on issues the following output in test.out : 但是,在USE2FILES上运行这段代码会在test.out发出以下输出:

test_stdout1
test_stdout2
test_stdout3

If I then disable USE2FILES I get: 如果然后禁用USE2FILES,则会得到:

test_stderr1
test_stderr2
test_stderr3
test_stdout1
test_stdout2
test_stdout3

Seems like in the first case no output towards stderr gets through. 在第一种情况下,似乎没有输出传递给stderr Is this behavior to be expected (am I missing something)? 这是预期的行为(我错过了什么)吗?

EDIT : After accepted Chris Dodd's answer: That's indeed a poor example. 编辑 :在接受克里斯·多德(Chris Dodd)的回答后:这确实是一个糟糕的例子。 Changing the fprintf sequence to something like this: fprintf序列更改为如下所示:

    fprintf(stderr, "test_stderr+++++++++++++++++++++++++++++++++++++++++++++++++1\n");
    fprintf(stdout, "test_stdout----------------------------------------1\n");
    fprintf(stderr, "test_stderr++++++++++++++++++++++++++++++++++2\n");
    fprintf(stdout, "test_stdout----------------2\n");
    fprintf(stderr, "test_stderr++++++++++++++++++++++++++++3\n");
    fprintf(stdout, "test_stdout----------------------3\n");

gets me this test.out output: 让我这个test.out输出:

test_stdout----------------------------------------1
test_stdout----------------2
test_stdout----------------------3
err++++++++++++++++++++++++++++3

showing pretty clearly stdout & stderr are competing with their writes over the same file. 清楚地显示stdoutstderr在同一个文件上进行写操作竞争。

If you do two open calls, you get two distinct kernel filehandles, each with its own I/O cursor (file offset), so writes to the two file descriptors will overwrite each other. 如果执行两次open调用,则会得到两个不同的内核文件句柄,每个句柄都有其自己的I / O游标(文件偏移),因此对这两个文件描述符的写入将相互覆盖。 If you use a single open call, you only get a single filehandle that both file descriptors refer to, so each write (to each descriptor) will advance the output offset so the next write (with the other file descriptor) will write after it. 如果使用单个open调用,则只会得到两个文件描述符都引用的单个文件句柄,因此每次写入(对每个描述符)都将使输出偏移量前进,因此下一次写入(与另一个文件描述符)将在其后写入。

In your example, the strings written are the exact same length, so the write to stdout exactly overwrites the preceeding write to stderr . 在您的示例中,写入的字符串长度完全相同,因此对stdout的写入将完全覆盖对stderr的先前写入。 Note that the file write only occurs when the FILE object is flushed, not (necessarily) when fprintf is called. 请注意,仅在刷新FILE对象时才会发生文件写入,而在调用fprintf时不会(有必要)发生文件写入。

You could also get the effect you seem to be trying to get by opening the files in O_APPEND mode. 您还可以通过在O_APPEND模式下打开文件来获得想要的效果。 This will cause every write to reposition the write offset to the current end of the file just before actually writing. 这将导致每次写入都在实际写入之前将写入偏移重新定位到文件的当前末端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM