此文是针对UNIX环境高级编程的出错处理程序的编写讲解的,系统基于ubuntu16.04
在编写出错处理程序前,我们需要了解一些日志文件相关的知识。日志文件基本上是为没有控制终端的守护进程准备的,每个守护进程的出错记录都记录在相应的日志文件上。比如cron对应的日志文件是/var/log/cron.log,mail对应的日志文件是/var/log/mail.log等。详细的日志文件的知识还是在另外的篇幅说明,
这里只要知道我们为我们自己编写的守护进程编写出错处理程序其实就是调用函数将出错信息重定向到/var/log/里面的一个文件中。以前我们可能输出在控制台或自己创建的文件中。这里只是换了个形式而已。
为什么不输出到控制台呢?
守护进程那么多,如果都输出到控制台你能想象你的控制台变成什么样了吗?而且也不方便以后查看
为什么不输出到我们自己的文件?
如果你每写一个守护进程就创建一个文件记录出错,那么多文件你记得住吗?如果以后要查看怎么办?
实现机制:
syslog机制负责发送、记录系统内核及工具所产生的信息,由syslog()调用、syslogd守护进程和配置文件/etc/rsyslog.conf组成。当系统内核及工具产生信息时,通过调用syslog(),把信息送往syslogd,syslogd再根据/etc/rsyslog.conf中的配置要求,将这些信息分别作如下处理:
记录到系统日志中
输出到系统控制台上
转发给指定的用户
通过网络转发给其他主机上的syslogd
rsyslog.conf文件中有个$IncludeConfig字段,它的意思就是把该字段后面的文件包含进来,一般是把/etc/rsysconfig.d/目录下以.conf结尾的文件都包含进来了,你学习一下这个目录下的文件的内容对这方面会大有裨益。
API:
-
#include<syslog.h>
-
void openlog(const char*ident,int option,int facility)
-
void syslog(int priority,const char*format,...)
-
void closelog(void)
-
int setlogmask(int maskpri)
openlog:
意思就是我打开什么类型的日志文件,
第一个参数随便一个字符串哪怕null也行,一般我们都设为程序名,因为这个字符串会加到我将发送给日志文件的消息中,所以设为程序名方便我们辨认这则消息是哪个程序发出的,
第二个参数有LOG_CONS,LOG_NDELAY,LOG_NOWAIT,LOG_ODELAY,LOG_PERROR,LOG_PID,具体意思我就不写了,自己查看。
第三个参数的目的就是确定我们日志文件的类型,之前我说过有cron,mail等。syslogd守护进程会根据日志类型到配置文件中查找此类型应写入的文件,若找到匹配项,则将之后我们发送的消息写入此文件中。它的参数有LOG_AUTH,LOG_AUTHPRIV,LOG_CRON,LOG_DAEMON,LOG_FTP,LOG_KERN,LOG_LOCAL0,...LOG_LOCAL7,LOG_LPR,LOG_MAIL,LOG_NEWS,LOG_SYSLOG,LOG_USER,LOG_UUCP。
openlog可以不调用,因为如果你不调用,那么当你调用syslog时系统会自动调用openlog,此时priority参数必须是facility和level的组合。ident被设置为null。
syslog:
调用此函数则将相应信息写到日志文件中,如果之前未调用openlog则priority参数是priority和level的组合(或运算),如果调用了就是单独的值,可取参数是LOG_EMERG,LOG_ALERT,LOG_CRIT,LOG_ERR,LOG_WARNING,LOG_NOTICE,LOG_INFO,LOG_DEBUG。优先级从高到低。format和printf函数的format一样,里面的占位符对应第三个参数。这就是将要发送的信息。
closelog:
此函数也是可以不调用的,它的作用是关闭曾与syslogd守护进程通信的描述符,之前我们说过这是通过UNIX域套接字实现的,这是需要一个监听描述符的,在你学过unix域套接字后这些概念就清楚了,此处不讨论,只要知道此函数调不调用都无所谓就行了。
setlogmask:
此函数的参数取值范围和openlog函数的facility的取值范围一样,多个类型可进行或运算,凡是加入到此参数中的类型,都不可用syslog将消息发送到此类型对应的日志文件中。比如
-
#include<syslog.h>
-
#include<stdio.h>
-
int main(void)
-
{
-
setlogmask(LOG_MAIL);
-
syslog(LOG_MAIL | LOG_ERR,"hello,%s","world");
-
return 0;
-
}
字符串"hello,world"永远不会被发送到mail.log中,因为调用setlogmask把它屏蔽掉了。
最后,再提一个syslog的变体:
-
#include<syslog.h>
-
#include<stdarg.h>
-
-
void vsyslog(int priority,const char*format,va_list arg)
va_list的用法参考只要学一下stdarg.h头文件就会了,这个头文件里面内容不多。
阅读(5150) | 评论(0) | 转发(0) |