将stderr重定向到C中的文件和stdout
是否有办法将错误消息写入日志文件并在终端屏幕上打印 我尝试了以下方法:将stderr重定向到C中的文件和stdout,c,logging,posix,stderr,C,Logging,Posix,Stderr,是否有办法将错误消息写入日志文件并在终端屏幕上打印 我尝试了以下方法: dup2(fileno(pFile), STDERR_FILENO); /* redirect stderr to file */ 将stderr重定向到文件。但是,这会将错误消息写入文件,但不会在屏幕上显示 这可以在不读取stderr的内容并将其复制到文件中的情况下完成吗 注意:我不想调用shell(system,popen)。我确实查看了coreutils的tee命令的实现。它将标准流复制到文件。使用管道连接到tee命
dup2(fileno(pFile), STDERR_FILENO); /* redirect stderr to file */
将stderr重定向到文件。但是,这会将错误消息写入文件,但不会在屏幕上显示
这可以在不读取stderr的内容并将其复制到文件中的情况下完成吗
注意:我不想调用shell(system,popen)。我确实查看了
coreutils
的tee
命令的实现。它将标准流复制到文件。使用管道连接到tee
命令
pFile = popen("tee logfile", "w");
dup2(fileno(pFile), STDERR_FILENO);
您必须“手动”复制数据以将其发送到两个地方,尽管使用linux特定的tee和splice系统调用可以使其稍微更有效(注意tee syscall而不是tee命令)
听起来你可能知道怎么做,只是希望不知道,但对其他人来说,解决方案可能是:
将原始stderr(通常是终端)复制到新的文件描述符以保存它。然后用pipe()制作一个管道。dup2将管道的写入端写入fd 2。关闭原始写入端fd。现在你的标准是管道。启动线程或进程。在这个线程中,您将数据从管道的读取端复制到文件和保存的原始stderr中。当线程或进程读取管道时,关闭它并退出
popen(“tee”)解决方案是相同的,只是它创建了一个额外的shell进程(并且您必须正确地引用传递给shell的文件名,以防其中有特殊字符…确保测试大于符号、空格和引号的奇怪文件名…)。如果使用popen,我认为您可能还存在一个(化妆品?)问题,即您无法关闭(),因为您的stderr将停止工作,因此您将始终保留一个额外的fd打开,并且不会等待孩子
如果您使用的是GLib之类的工具,那么它有一个g_spawn_async函数族,可以用来生成tee命令,而不需要shell。否则,您必须手动执行fork/exec操作,以避免使用shell;您可以执行tee命令,也可以fork而不是exec-只需在fork之后让子代码执行stderr复制,不要依赖tee命令。或者,您可以使用线程而不是进程
如果使用fork,您可能会发现gspawn.c中的源代码很有用;例如,在任何复杂的程序中,FD_CLOEXEC不是unix上的默认值都是一场噩梦,而且很容易让子级继承导致问题的描述符。
避免僵尸进程并处理所有错误和诸如此类的事情也很烦人
无论如何,是的,它的代码比人们希望的要多,但是在coreutils中的tee源代码和gspawn.c之间,您可能可以复制大部分代码。唯一的选择是将所有错误消息同时写入
pFile
和stderr
。没有内置的方法可以同时写入两个目的地。您可以尝试“tail”在屏幕上查看输出文件。这是最简单的解决方案。@orcnc我怎么知道要尾多少行?你不必知道行数。它始终显示最后n行数。如果您正在寻找一个特定的模式,您可以很容易地将tail与grep结合起来,并获得一个强大的日志查看器。非常感谢。此外,这是类似的帖子:。然而,在这种情况下,你的答案是解决我的需要。