如何在C中关闭stdout和stderr?
我需要关闭我的 C 程序之一的标准输出和标准错误。正在执行的程序怎么可能不退出呢?
I need to close stdout and stderr for one of my C program. How is it possible without exiting the program in execution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
实际上你也可以使用
close
函数:Actually you can also use the
close
function:您可以尝试一下有关标准输出的内容。它不会关闭 stdout,但会将 stdout 重定向到 NULL。我相信你也可以对 stderr 做同样的事情。它在我的情况下有效(Linux/GCC)(它应该在 Unix 和 Windows 中都有效,但我还没有在 Windows 中进行测试)。
这个解决方案的优点是标准输出永远不会关闭。因此,可以根据需要随时恢复原始标准输出。我们也不会有将 stdout 文件描述符分配给另一个输出流的任何风险。
You can try this about stdout. It will not close stdout, but it will redirect stdout to NULL. I believe you could do the same for stderr. It worked in my situation (Linux/GCC) (It should works in both Unix and Windows, but I have not test in Windows).
The advantage of this solution is stdout is never closed. So, the original stdout can be restored at any time as it is necessary. We also do not have any risk of stdout file descriptor be assigned to another output stream.
您可以:
对于任何想知道为什么要这样做的人来说,这对于 Unix 上的守护进程/服务进程来说是一个相当常见的任务。
但是您应该意识到关闭文件描述符可能会产生意想不到的后果:
fopen
该文件描述符(至少在 Linux 上)将替换 fd 1,即 stdout。随后使用此文件的任何代码都将写入此文件,这可能不是您想要的。FILE*
指针的注释。具体来说:stdout
或stderr
(它们是FILE*
指针(请参阅 它们的定义)然后在FILE*
关闭时写入这些内容是未定义的这可能会以意想不到的方式使您的程序崩溃,并不总是在错误发生时参见未定义的行为。 .快速的一行解决方案是
freopen()
表示 Linux/OSX 下的/dev/null
、/dev/console
或nul
在 Windows 上。或者,您可以使用特定于平台的实现根据需要重新打开文件描述符/句柄。You can just:
For anybody wondering why you might want to do this, this is a fairly common task for a daemon/service process on Unix.
However you should be aware that closing a file descriptor may have unintended consequences:
fopen
that file descriptor (on Linux, at least) will replace fd 1, i.e. stdout. Any code that subsequently uses this will write to this file, which may not be what you intended.FILE*
pointers. Specifically:stdout
orstderr
(which areFILE*
pointers (see their definition) then writing to these whilstFILE*
is closed is undefined behaviour. This will likely crash your program in unexpected ways, not always at the point of the bug either. See undefined behaviour.The quick, one-line solution is to
freopen()
To say/dev/null
,/dev/console
under Linux/OSX ornul
on Windows. Alternatively, you can use your platform-specific implementation to re-open the file descriptors/handles as required.你尝试了什么?
fclose
不起作用吗?What have you tried? Doesn't
fclose
work?如果您想阻止应用程序写入控制台,则:
输出:
注意:在文件关闭后任何使用 FILE 指针的尝试都是错误的。在本例中,我这样做只是为了说明关闭这些文件描述符可能会对您的应用程序造成什么影响。
If you want to prevent your application from writing to the console, then:
Outputs:
Note: any attempt to use a FILE pointer after the file is closed is erroneous. I'm doing it in this case just to illustrate what closing these file descriptors might do to your application.
警告:我根本没有 C 语言经验,但最近读了一张由 RedHat 员工兼 GNUlib 维护者 Jim Meyering 直接回答这个问题的幻灯片:https://www.gnu.org/ghm/2011/paris/slides/jim-meyering-goodbye-world。 pdf。我只是总结一下。
TL;DR
获取 closeout .c 及其从 GNUlib 到源代码的依赖项,并
作为 main 中的第一行进行调用。
摘要
首先,一些警告,引用 POSIX:
关闭流而不处理其错误并不健壮,对于 stdout 和 stderr 也是如此。以下是您需要处理的错误列表:
fclose(stdout)
ferror(stdout)
又名先前的错误__fpending(stdout)
又名东西不是 那样处理这些错误,正如 GNUlib 在 close- 中实现的 Stream.c,引用如下。
注意:
__fpending
是 glibc 特有的,可能不可移植。 OTOH,正在标准化 作为fpending
。附:
如果您根据 http:// 编写守护进程,那么这不是关闭 stdout 和 stderr 的好理由/cloud9.hedgee.com./scribbles/daemon#logging。您应该让守护进程管理器(例如守护进程工具、runit、s6、nosh、OpenRC 和 systemd)处理重定向。
但是,您仍然应该关闭程序最终写入的任何流以检查错误。引用 close-stream.c:
Warning: I am not experienced in C at all, but recently read a slide that answers this question directly by Jim Meyering, a RedHat employee and GNUlib maintainer: https://www.gnu.org/ghm/2011/paris/slides/jim-meyering-goodbye-world.pdf. I merely summarize.
TL;DR
Get closeout.c and its dependencies from GNUlib into your source and call
as your first line in main.
Summary
First, some heads up warning, quoting POSIX:
Closing stream without handling its errors is not robust, and it is the same for stdout and stderr. Here is a list of errors you need to handle:
fclose(stdout)
ferror(stdout)
a.k.a. previous error__fpending(stdout)
a.k.a. stuff not flushedHandling these errors, as GNUlib implements in close-stream.c, is quoted below.
Notice:
__fpending
is special to glibc and may not be portable. OTOH, it is on the way to be standardized asfpending
.P.S.:
That is not a good reason to close stdout and stderr if you are writing a daemon according to http://cloud9.hedgee.com./scribbles/daemon#logging. You should let a daemon manager (such as daemon tools, runit, s6, nosh, OpenRC and systemd) handle the redirection.
However, you still should close any stream that the program has ever written to in the end to check for errors. Quote from close-stream.c: