`
javatoyou
  • 浏览: 1016290 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Linux下syslog日志函数使用

 
阅读更多

许多应用程序需要记录它们的活动。系统程序经常需要向控制台或日志文件写消息。这些消息可能指示错误、警告或是与系统状态有关的一般信息。例如,su程序会把某个用户尝试得到超级用户权限但失败的事实记录下来。

通常这些日志信息被记录在系统文件中,而这些系统文件又被保存在专用于此目的的目录中。它可能是/usr/adm或/var/log目录。对一个典型的Linux安装来说,文件 /var/log/messages包含所有系统信息,/var/log/mail包含来自邮件系统的其他日志信息,/var/log/debug可能包 含调试信息。你可以通过查看/etc/syslog.conf文件来检查系统配置。

下面是一些日志信息的样例:


这里,我们可以看到记录的各种类型的信息。前几个是Linux内核在启动和检测已安装硬件时自己报告的信息。接着是任务安排程序cron报告它正在启动。最后,su程序报告用户neil获得了超级用户权限。

查看日志信息可能需要有超级用户特权。

有些UNIX系统并不像上面这样提供可读的日志文件,而是为管理员提供一些工具来读取系统事件的数据库。具体情况请参考系统文档。

虽然系统消息的格式和存储方式不尽相同,可产生消息的方法却是标准的。UNIX规范为所有程序提供了一个接口,通过syslog函数来产生日志信息:


syslog函数向系统的日志工具发送一条日志信息。每条信息都有一个priority参数,该参数是一个严重级别与一个设施值的按位或。严重级别控制日志信息的处理,设施值记录日志信息的来源。

定义在头文件syslog.h中的设施值包括LOG_USER(默认值)——它指出消息来自一个用户应用程序,以及LOG_LOCAL0、LOG_LOCAL1直到LOG_LOCAL7,它们的含义由本地管理员指定。

严重级别按优先级递减排列,如表4-6所示。

表 4-6

优 先 级
说 明

LOG_EMERG
紧急情况

LOG_ALERT
高优先级故障,例如数据库崩溃

LOG_CRIT
严重错误,例如硬件故障

LOG_ERR
错误

LOG_WARNING
警告

LOG_NOTICE
需要注意的特殊情况

LOG_INFO
一般信息

LOG_DEBUG
调试信息

根据系统配 置,LOG_EMERG信息可能会广播给所有用户,LOG_ALERT信息可能会EMAIL给管理员,LOG_DEBUG信息可能会被忽略,而其他信息则 写入日志文件。当我们编写的程序需要使用日志记录功能时,只要在希望创建一条日志信息时简单的调用syslog函数即可。

syslog创建的日志信息包含消息头和消息体。消 息头根据设施值及日期和时间创建。消息体根据syslog的message参数创建,该参数的作用类似printf中的格式字符串。syslog的其他参 数要根据message字符串中printf风格的控制转换符而定。此外,控制转换符%m可用于插入与错误变量errno当前值对应的出错消息字符串。这 对于记录错误消息很有用。

实验:syslog函数

在这个程序中,我们试图打开一个不存在的文件:


编译并运行这个程序syslog.c,我们没有看到输出,但是/var/log/messages文件现在在尾部有如下一行:

Feb 8 09:59:14 beast syslog: oops - No such file or directory

实验解析

在这个程序中,我们试图打开一个不存在的文件。在文件打开失败后,我们调用syslog在系统日志中记录这一事件。

注意:日志信息并未指明是哪个程序调用了日志功能,它仅仅记录syslog被调用以记录一条信息的事实。%m转换控制符被替换为一个错误描述,在本例中就是“文件没有找到”。这比仅仅报告一个原始的错误码更有用。

在头文件syslog.h中还定义了一些能够改变日志记录行为的其他函数。它们是:


我们可以通过调用openlog函数来改变日志信息 的表示方式。它允许我们设置一个字符串ident,该字符串会加在日志信息的前面。我们可以通过它来指明是哪个程序创建了这条信息。facility参数 记录一个设施值,它将作为后续syslog调用的默认设施值。它的默认值是LOG_USER。logopt参数对后续syslog调用的行为进行配置,它是0个或多个表4-7中值的按位或。

表 4-7

logopt参数
说 明

LOG_PID
在日志信息中包含进程标识符,这是系统分配给每个进程的一个唯一值

LOG_CONS
如果信息不能被记录到日志文件中,就把它们发送到控制台

LOG_ODELAY
在第一次调用syslog时才打开日志功能

LOG_NDELAY
立即打开日志功能,而不是等到第一次记录日志时

openlog函数会分配并打开一个文件描述符,并通过它来写日志。你可以使用closelog函数来关闭它。注意,在调用syslog之前无需调用openlog,因为syslog会根据需要自行打开日志功能。

我们可以通过setlogmask函数来设置一个日志掩码,并通过它来控制日志信息的优先级。优先级未在日志掩码中置位的后续syslog调用都将被丢弃。例如,你可以通过这个方法关闭LOG_DEBUG消息而不用改变程序主体。

我们可以用LOG_MASK(priority)为日志信息创建一个掩码,它的作用是创建一个只包含一个优先级的掩码。我们还可以用LOG_UPTO(priority)来创建一个由指定优先级之前的所有优先级(包括指定优先级)构成的掩码。

实验:logmask程序

在本例中,我们将看到日志掩码的作用:


logmask.c程序没有输出,但是在一个典型的Linux系统中,在/var/log/messages文件尾部,我们会看到如下信息:

Feb 8 10:00:50 beast logmask[1833]: informative message, pid = 1833

接收调试日志信息的文件(根据日志配置而定,通常是/var/log/debug,有时也可能是/var/log/messages)会包含如下信息:

Feb 8 10:00:50 beast logmask[1833]: debug message, should appear

实验解析

这个程序用它自己的名字logmask初始化日志功 能,并要求日志信息中包含进程标识符。一般信息记录到文件/var/log/messages,调试信息记录到文件/var/log/debug。第二个 调试信息没有出现,因为我们调用setlogmask忽略了优先级低于LOG_NOTICE的所有信息(注意,这种做法在早期Linux内核中可能不支持)。

如果你的Linux安装版本没有启用调试信息日志功 能,或者采用的是其他配置情况,你可能看不到调试信息。要启用所有的调试信息,需把下面一行内容添加到/etc/syslog.conf文件的尾部并重启 系统(你也可以简单地向syslogd进程发送一个挂起信号)。然而,不管如何,最好认真查看你的系统文档以了解配置文件的正确格式。

*.debug /var/log/debug

logmask.c用到了getpid函数,它和与其紧密相关的getppid函数的定义如下所示:


这两个函数分别返回调用进程和调用进程的父进程的进程标识符(PID)。

使用syslog()函数处理日志信息

函数声明:

#include <syslog.h>

void syslog(int priority, const char *message, arguments...);

priority参数的格式(severity level|facility code)

示例:

LOG_ERR|LOG_USER

severity level:

Priority Level Description

LOG_EMERG An emergency situation

LOG_ALERT High-priority problem, such as database corruption

LOG_CRIT Critical error, such as hardware failure

LOG_ERR Errors

LOG_WARNING Warning

LOG_NOTICE Special conditions requiring attention

LOG_INFO Informational messages

LOG_DEBUG Debug messages

facility value(转自syslog.h头文件):

/* facility codes */

#define LOG_KERN (0<<3) /* kernel messages */

#define LOG_USER (1<<3) /* random user-level messages */

#define LOG_MAIL (2<<3) /* mail system */

#define LOG_DAEMON (3<<3) /* system daemons */

#define LOG_AUTH (4<<3) /* security/authorization messages */

#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */

#define LOG_LPR (6<<3) /* line printer subsystem */

#define LOG_NEWS (7<<3) /* network news subsystem */

#define LOG_UUCP (8<<3) /* UUCP subsystem */

#define LOG_CRON (9<<3) /* clock daemon */

#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */

#define LOG_FTP (11<<3) /* ftp daemon */

示例代码:

#include <syslog.h>

#include <stdio.h>

int main(void)

{

FILE *f;

f = fopen("abc","r");

if(!f)

syslog(LOG_ERR|LOG_USER,"test - %m/n");

}

上面的日志信息由系统自动给出,我们也可过滤日志信息。用到以下函数:

#include <syslog.h>

void closelog(void);

void openlog(const char *ident, int logopt, int facility);

int setlogmask(int maskpri);

logopt参数的选项:

logopt Parameter Description

LOG_PID Includes the process identifier, a unique number allocated to each process by the system, in the messages.

LOG_CONS Sends messages to the console if they can’t be logged.

LOG_ODELAY Opens the log facility at first call to .

LOG_NDELAY Opens the log facility immediately, rather than at first log.

示例代码:

#include <syslog.h>

#include <stdio.h>

#include <unistd.h>

int main(void)

{

int logmask;

openlog("logmask", LOG_PID|LOG_CONS, LOG_USER); /*日志信息会包含进程id。*/

syslog(LOG_INFO, "informative message, pid=%d", getpid());

syslog(LOG_DEBUG,"debug message, should appear"); /*记录该日志信息。*/

logmask = setlogmask(LOG_UPTO(LOG_NOTICE)); /*设置屏蔽低于NOTICE级别的日志信息。*/

syslog(LOG_DEBUG, "debug message, should not appear"); /*该日志信息被屏蔽,不记录。*/

}

不同安全级别的日志信息存放在/var/log目录下的哪个文件中是由/etc/syslog.conf文件控制的,下面是我系统中syslog.conf文件的内容:

# /etc/syslog.conf Configuration file for syslogd.

#

# For more information see syslog.conf(5)

# manpage.

#

# First some standard logfiles. Log by facility.

#

auth,authpriv.* /var/log/auth.log

*.*;auth,authpriv.none -/var/log/syslog

#cron.* /var/log/cron.log

daemon.* -/var/log/daemon.log

kern.* -/var/log/kern.log

lpr.* -/var/log/lpr.log

mail.* -/var/log/mail.log

user.* -/var/log/user.log

uucp.* /var/log/uucp.log

#

# Logging for the mail system. Split it up so that

# it is easy to write scripts to parse these files.

#

mail.info -/var/log/mail.info

mail.warn -/var/log/mail.warn

mail.err /var/log/mail.err

# Logging for INN news system

#

news.crit /var/log/news/news.crit

news.err /var/log/news/news.err

news.notice -/var/log/news/news.notice

#

# Some `catch-all' logfiles.

#

*.=debug;/

auth,authpriv.none;/

news.none;mail.none -/var/log/debug

*.=info;*.=notice;*.=warn;/

auth,authpriv.none;/

cron,daemon.none;/

mail,news.none -/var/log/messages

#

# Emergencies are sent to everybody logged in.

#

*.emerg *

#

# I like to have messages displayed on the console, but only on a virtual

# console I usually leave idle.

#

#daemon,mail.*;/

# news.=crit;news.=err;news.=notice;/

# *.=debug;*.=info;/

# *.=notice;*.=warn /dev/tty8

# The named pipe /dev/xconsole is for the `xconsole' utility. To use it,

# you must invoke `xconsole' with the `-file' option:

#

# $ xconsole -file /dev/xconsole [...]

#

# NOTE: adjust the list below, or you'll go crazy if you have a reasonably

# busy site..

#

daemon.*;mail.*;/

news.crit;news.err;news.notice;/

*.=debug;*.=info;/

*.=notice;*.=warn |/dev/xconsole

实例代码:

1 #include <string>
2 #include <iostream>
3 #include <algorithm>
4 #include <list>
5 #include <syslog.h>
6 using namespace std ;
7
8 //===============================================

9
10 class TLOG
11 {
12 public:
13 TLOG() ;
14 ~TLOG() ;
15 TLOG& operator<<( const char * p ) ;
16 TLOG& operator<<( string & s ) ;
17 TLOG& operator<<( TLOG& (* pfun)(TLOG&) ) ;
18
19 void debug( const char * p ) ;
20 void debug( string & s ) ;
21
22 void log( const char * p ) ;
23 void log( string & s ) ;
24 } ;
25 TLOG& endl( TLOG& object ) ;
26
27 const char * LOG_PREFIX = "root_log : " ;
28
29 TLOG glog ;
30
31 TLOG::TLOG()
32 {
33 #ifdef LOG_SYSLOGD
34 openlog( LOG_PREFIX, LOG_PID, LOG_USER ) ;
35 #endif
36 }
37 TLOG::~TLOG()
38 {
39 #ifdef LOG_SYSLOGD
40 closelog() ;
41 #endif
42 }
43
44 TLOG& TLOG::operator<<( const char * p )
45 {
46 #ifdef LOG_STDOUT
47 cout << p ;
48 #endif
49 return *this ;
50 }
51
52 TLOG& TLOG::operator<<( string & s )
53 {
54 #ifdef LOG_STDOUT
55 cout << s ;
56 #endif
57 return *this ;
58 }
59 TLOG& TLOG::operator<<( TLOG& (* pfun)(TLOG&) )
60 {
61 return pfun(*this) ;
62 }
63 TLOG& endl( TLOG& object )
64 {
65 #ifdef LOG_STDOUT
66 cout << endl ;
67 #endif
68 return object ;
69 }
70
71 void TLOG::debug( const char * p )
72 {
73 *this << p ;
74 return ;
75 }
76 void TLOG::debug( string & s )
77 {
78 *this << s ;
79 return ;
80 }
81
82 void TLOG::log( const char * p )
83 {
84 *this << LOG_PREFIX << p << endl ;
85
86 #ifdef LOG_SYSLOG
87 syslog( LOG_INFO, p ) ;
88 #endif
89 return ;
90 }
91 void TLOG::log( string & s )
92 {
93 *this << LOG_PREFIX << s << endl ;
94
95 #ifdef LOG_SYSLOG
96 syslog( LOG_INFO, s.c_str() ) ;
97 #endif
98 return ;
99 }
100
101 int
102 main(void)
103 {
104 glog.log("yeetec" );
105 // glog.debug(__func__);

106 string word;
107 cout<<"Enter a line:";
108 cin>>word;
109 while(cin.get()!='/n')
110 continue;
111 cout<<word<<"is all"<<"wanted!/n";
112
113 string line;
114 cout<<"Enter a line:(really)";
115 getline(cin,line);
116 cout<<"line:"<<line<<endl;
117 return 0;
118 }

结果:

ct 16 16:01:42 zerk a.out: yeetec





本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/telehiker/archive/2007/10/18/1830575.aspx

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics