我一直在想,堵塞的目的是什么?据我所知,clog与cerr相同,但具有缓冲功能,因此效率更高。通常stderr与stdout相同,因此clog与cout相同。这对我来说似乎很la脚,所以我认为我一定会误会它。如果我将日志消息发送到同一位置,将错误消息发送到同一位置(也许在/ var / log / messages中),那么我可能不会写太多消息(因此,使用non命令不会造成太多损失)缓冲的cerr)。以我的经验,我希望我的日志消息是最新的(非缓冲的),以便我可以帮助查找崩溃(因此,我不想使用缓冲的木log)。显然我应该一直使用cerr。
我希望能够重定向程序内部的阻塞。重定向cerr很有用,这样当我调用库例程时,我可以控制cerr和clog的去向。一些编译器可以支持吗?我刚刚检查了DJGPP,并将stdout定义为FILE结构的地址,因此执行" stdout = freopen(...)"之类的操作是非法的。
-
是否可以重定向阻塞,cerr,cout,stdin,stdout和/或stderr?
-
clog和cerr之间唯一的区别是缓冲吗?
-
我应该如何实施(或找到)更强大的日志记录功能(请链接)?
Is it possible to redirect clog, cerr, cout, stdin, stdout, and/or stderr?
是。您需要rdbuf函数。
1 2 3
| ofstream ofs("logfile");
cout.rdbuf(ofs.rdbuf());
cout <<"Goes to file." << endl; |
Is the only difference between clog and cerr the buffering?
据我所知,是的。
如果您在posix shell环境中(我真的在考虑bash),则可以重定向任何
文件描述符到任何其他文件描述符,因此要重定向,您可以:
将stderr重定向到fd = 5表示的文件。
编辑:再三考虑,我更喜欢@Konrad Rudolph关于重定向的答案。 rdbuf()是一种更一致且可移植的方法。
至于日志记录,...我从Boost库开始,处理所有不在std库中的C ++。看一下:Boost Logging v2
编辑:Boost日志记录不是Boost库的一部分;它已经过审查,但未被接受。
编辑:2年后的2010年5月,Boost接受了一个日志库,现在称为Boost.Log。
当然,还有其他选择:
-
Log4Cpp(C ++的log4j样式的API)
-
Log4Cxx(Apache支持的log4j样式的API)
-
Pantheios(已消失?上次尝试时无法使它建立在最新的编译器上)
-
Google的GLog(提示@SuperElectric)
还有Windows事件记录器。
还有一些可能有用的文章:
-
登录C ++(Dobbs博士)
-
简化的日志记录和跟踪(Sun)
重新导向
关于如何重定向std::clog(std::wclog),Konrad Rudolph的回答很好。
好。
其他答案告诉您各种可能性,例如使用命令行重定向(例如2>output.log)。在Unix中,您还可以创建一个文件,并使用3>output.log之类的东西向命令添加另一个输出。然后,在程序中,您必须使用fd数字3打印日志。您可以继续正常打印到stdout和stderr。 Visual Studio IDE的CDebug命令具有类似的功能,该命令会将其输出发送到IDE输出窗口。
好。
stderr is the same as stdout?
Ok.
通常这是正确的,但是在Unix下,您可以将stderr设置为/dev/console,这意味着它会转到另一个tty(又称为终端)。这些天很少使用。我在IRIX上有这种方式。我将打开一个单独的X窗??口并查看其中的错误。
好。
系统日志
没提到的一件事,在Unix下,您也有syslog()。
好。
Linux(甚至可能是Mac OS / X)下的最新版本比以前具有更多功能。特别是,它可以使用标识和其他一些参数将日志重定向到特定文件(即mail.log)。 syslog机制可以在计算机之间使用,因此可以将计算机A的日志发送到计算机B。当然,您可以通过多种方式过滤日志,尤其是按严重性过滤日志。
好。
syslog()的使用也非常简单:
好。
1
| syslog(LOG_ERR,"message #%d", count++); |
它提供8个级别(或严重性),格式为la printf()以及该格式的参数列表。
好。
以编程方式,如果您首先调用openlog()函数,则可能需要进行一些调整。您必须在第一次调用syslog()之前调用它。
好。
如unixman83所述,您可能想要使用宏。这样,您可以在邮件中包含一些参数,而不必一遍又一遍地重复它们。也许是这样的(请参见可变参数宏):
好。
1 2 3
| // (not tested... requires msg to be a string literal)
#define LOG(lvl, msg, ...) \
syslog(lvl, msg" (in" __FILE__":%d)", __VA_ARGS__, __LINE__) |
您可能还会发现__func__有用。
好。
重定向,过滤等是通过创建配置文件来完成的。这是我的snapwebsites项目的示例:
好。
1 2 3
| mail.err /var/log/mail/mail.err
mail.* /var/log/mail/mail.log
& stop |
我将文件安装在etc/rsyslog.d/下,并且syslog服务器自动处理该更改并将所有与邮件相关的日志保存到这些文件夹中。
好。
注意:我还必须创建/va/log/mail文件夹和该文件夹中的文件,以确保它们都正常工作(因为否则邮件守护程序可能没有足够的权限。)
好。
快照程序(一点插头)
我使用过log4cplus,从1.2.x版本开始,它就相当不错。我对此有三个缺点:
好。
如果我想调用fork(),它需要我完全清除所有内容;不知何故,它在fork()调用中无法正常运行...(至少在我拥有的版本中)
在我希望管理员无需修改原始文件即可进行更改的环境中,配置文件(.properties)难以管理
它使用的是C ++ 03,我们现在已经在2019年了……我想至少要有C ++ 11
因此,尤其是由于第(1)点,我编写了自己的版本称为snaplogger。但是,这并不是一个完全独立的项目。我使用了snapcpp环境中的许多其他项目(仅获取snapcpp并运行bin/build-snap脚本或仅从启动板获取二进制文件就容易得多。)
好。
使用诸如snaplogger或log4cplus之类的记录器的优点是,您通常可以定义任意数量的目标和许多其他参数(例如syslog()提供的严重性级别)。 log4cplus能够将其输出发送到许多不同的位置:文件,系统日志,MS-Windows日志系统,控制台,服务器等。请查看这两个项目中的附加程序,以了解可能性列表。这里有趣的因素是任何日志都可以发送到所有目的地。拥有一个名为all.log的文件很有用,您的所有服务都会在其中发送日志。这样可以理解某些错误,当并行运行许多服务时,使用单独的日志文件不那么容易。
好。
这是快照记录器配置文件中的一个简单示例:
好。
1 2 3 4 5 6 7 8
| [all]
type=file
lock=true
filename=/var/log/snapwebsites/all.log
[file]
lock=false
filename=/var/log/snapwebsites/firewall.log |
请注意,对于all.log文件,我需要一个锁,因此多个编写器不会破坏彼此之间的日志。 部分不是必需的,因为我只有一个进程(没有线程)。
好。
两者都为您提供了添加自己的附加程序的方法。因此,例如,如果您有一个带有输出窗口的Qt应用程序,则可以编写一个附加程序,将SNAP_LOG_ERROR()调用的输出发送到该窗口。
好。
snaplogger还为您提供了一种扩展消息中变量支持的方法(也称为格式)。例如,我可以使用${date}变量插入日期。然后,我可以使用参数对其进行调整。要仅输出年份,请使用${date:year}。此变量和参数支持也是可扩展的。
好。
snaplogger可以按严重性(如syslog),正则表达式和组件过滤输出。我们有一个normal和一个secure组件,默认值为normal。我希望将发送到secure组件的日志写入安全文件。这意味着在一个子目录中,该目录比大多数管理员可以查看的常规日志受到更多保护。当我运行HTTP服务时,有时会发送信息,例如信用卡的最后3位数字。我更喜欢将它们保存在安全日志中。也可能是与密码有关的错误。实际上,我认为是日志中的任何安全隐患。同样,组件是可扩展的,因此您可以拥有自己的组件。
好。
好。
由于这里有一些关于重定向的答案,因此,我将添加我最近偶然发现的关于重定向的这个漂亮的宝石:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <fstream>
#include <iostream>
class redirecter
{
public:
redirecter(std::ostream & dst, std::ostream & src)
: src(src), sbuf(src.rdbuf(dst.rdbuf())) {}
~redirecter() { src.rdbuf(sbuf); }
private:
std::ostream & src;
std::streambuf * const sbuf;
};
void hello_world()
{
std::cout <<"Hello, world!
";
}
int main()
{
std::ofstream log("hello-world.log");
redirecter redirect(log, std::cout);
hello_world();
return 0;
} |
基本上,这是一个重定向类,它允许您重定向任何两个流,并在完成后将其还原。
基本记录仪
1
| #define myerr(e) {CriticalSectionLocker crit; std::cerr << e << std::endl;} |
用作myerr("ERR:" << message);或myerr("WARN:" << message << code << etc);
是非常有效的。
然后做:
1 2
| ./programname.exe 2> ./stderr.log
perl parsestderr.pl stderr.log |
或者只是手动解析stderr.log
我承认这不是针对性能至关重要的代码。但是反正是谁写的。