Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将stderr重定向到C中的文件和stdout_C_Logging_Posix_Stderr - Fatal编程技术网

将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结合起来,并获得一个强大的日志查看器。非常感谢。此外,这是类似的帖子:。然而,在这种情况下,你的答案是解决我的需要。