如果stdout是文件,则stdout重定向不起作用

时间:2021-04-14 00:03:31

I am using code like the following to redirect stdout before calling a noisy function from an external library written in Fortran:

我在使用Fortran编写的外部库调用嘈杂函数之前,使用以下代码重定向stdout:

// copy standard output
out = dup(STDOUT_FILENO);

// close standard output
close(STDOUT_FILENO);

// use log file as standard output
log = open(log_file, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
if(log != STDOUT_FILENO)
    fprintf(stderr, "could not create log file %s", log_file);

// call the library function that uses a lot of printf
func();

// restore original standard output
dup2(out, STDOUT_FILENO);

// close copy of standard output
close(out);

To summarise my intention of the above code snippet: copy stdout, close stdout (frees file descriptor 0), open file (uses lowest file descriptor = 0 = stdout), run code with redirected stdout, and reset stdout.

总结一下我对上面代码片段的意图:复制stdout,关闭stdout(释放文件描述符0),打开文件(使用最低文件描述符= 0 = stdout),运行带有重定向标准输出的代码,然后重置标准输出。

This works perfectly well when I run my code using the terminal as stdout. However, when I set stdout to a file (using $ mycode > myfile.txt) the redirection fails, and I end up with the output of func() in myfile.txt instead of the log file. How is this possible?

当我使用终端作为stdout运行我的代码时,这非常有效。但是,当我将stdout设置为一个文件(使用$ mycode> myfile.txt)时,重定向失败,我最终在myfile.txt中输出func()而不是日志文件。这怎么可能?

1 个解决方案

#1


2  

You need to do fflush(stdout) before you restore the original stdout with dup2.

在使用dup2恢复原始标准输出之前,需要执行fflush(stdout)。

The reason it works with a terminal is because stdout is line buffered for a terminal. So your output gets flushed immediately to the redirected file. But when you start your program with stdout to a file, stdout becomes fully buffered, so your func output will be in a buffer waiting to be flushed. When you restore the original stdout without flushing, the output gets written to the original stdout when the program exits.

它与终端一起工作的原因是因为stdout是终端的线路缓冲。因此,您的输出会立即刷新到重定向的文件。但是当您使用stdout将文件启动到文件时,stdout会完全缓冲,因此您的func输出将位于等待刷新的缓冲区中。在不刷新的情况下恢复原始标准输出时,输出将在程序退出时写入原始标准输出。

#1


2  

You need to do fflush(stdout) before you restore the original stdout with dup2.

在使用dup2恢复原始标准输出之前,需要执行fflush(stdout)。

The reason it works with a terminal is because stdout is line buffered for a terminal. So your output gets flushed immediately to the redirected file. But when you start your program with stdout to a file, stdout becomes fully buffered, so your func output will be in a buffer waiting to be flushed. When you restore the original stdout without flushing, the output gets written to the original stdout when the program exits.

它与终端一起工作的原因是因为stdout是终端的线路缓冲。因此,您的输出会立即刷新到重定向的文件。但是当您使用stdout将文件启动到文件时,stdout会完全缓冲,因此您的func输出将位于等待刷新的缓冲区中。在不刷新的情况下恢复原始标准输出时,输出将在程序退出时写入原始标准输出。