syslogd架构

syslogd详解

  • App通过syslog的接口进行log的打印,该接口define在syslog.h中;
  • syslog会通过socket发送消息,将log发送给syslogd;
  • syslogd在获取到log后,会进行log的处理;
  • syslogd可以将log保存到本地,也可以发送到共享内存或远程服务器

 

openlog()

在syslog接口使用之前,有必要通过openlog进行一些log信息的初始化工作,openlog定义在系统头文件syslog.h中,函数原型:

void openlog (const char *__ident, int __option, int __facility)
  • 第一个参数为log tag,同Android中LOG_TAG;
  • 第二个参数为log flags,定义在syslog.h中;

如下:

#define	LOG_PID		0x01	/* log the pid with each message */
#define	LOG_CONS	0x02	/* log on the console if errors in sending */
#define	LOG_ODELAY	0x04	/* delay open until first syslog() (default) */
#define	LOG_NDELAY	0x08	/* don't delay open */
#define	LOG_NOWAIT	0x10	/* don't wait for console forks: DEPRECATED */
#define	LOG_PERROR	0x20	/* log to stderr as well */

例如:

使用LOG_PID,会在每一条log中添加pid信息;

使用LOG_CONS,在出现error信息的时候,会将log输出到congsole上。

  • 第三个参数为syslog 的facility,syslog.h中一共有23种选择;
/* 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 */

	/* other codes through 15 reserved for system use */
#define	LOG_LOCAL0	(16<<3)	/* reserved for local use */
#define	LOG_LOCAL1	(17<<3)	/* reserved for local use */
#define	LOG_LOCAL2	(18<<3)	/* reserved for local use */
#define	LOG_LOCAL3	(19<<3)	/* reserved for local use */
#define	LOG_LOCAL4	(20<<3)	/* reserved for local use */
#define	LOG_LOCAL5	(21<<3)	/* reserved for local use */
#define	LOG_LOCAL6	(22<<3)	/* reserved for local use */
#define	LOG_LOCAL7	(23<<3)	/* reserved for local use */

#define	LOG_NFACILITIES	24	/* current number of facilities */
#define	LOG_FACMASK	0x03f8	/* mask to extract facility part */
				/* facility of pri */
#define	LOG_FAC(p)	(((p) & LOG_FACMASK) >> 3)

例如:

  1. 使用LOG_KERN,表示log为kernel信息;
  2. 使用LOB_USER,表示log为普通用户信息,一般package使用的信息可以设为LOG_USER;
  3. 使用LOG_DAEMON,表示log为系统守护进程信息;

 

syslog()

对于syslogd来说,log是通过syslog传入的,函数的原型:

void syslog (int __pri, const char *__fmt, ...)

应用可以通过openlog进行初始化,例如log的tag信息或者是pid信息。如果不进行openlog而直接使用syslog也是可以的,在syslog中会进行openlog的操作。当然,不进行openlog操作,log中有些信息就无法显示,例如pid信息。

下面来看下syslog中的参数:

  • 第一个参数为log的优先级,与Android中的LOG_DEBUG或LOG_INFO等类似;
#define	LOG_EMERG	0	/* system is unusable */
#define	LOG_ALERT	1	/* action must be taken immediately */
#define	LOG_CRIT	2	/* critical conditions */
#define	LOG_ERR		3	/* error conditions */
#define	LOG_WARNING	4	/* warning conditions */
#define	LOG_NOTICE	5	/* normal but significant condition */
#define	LOG_INFO	6	/* informational */
#define	LOG_DEBUG	7	/* debug-level messages */

这里的priority定义与Android略有不同,例如LOG_CRIT表示critical的信息。

  • 第二个参数为log的具体信息,同printf;

 

closelog()

在使用syslog结束之后通过closelog进行扫尾工作。函数原型:

void closelog (void)

主要就是将socket 关闭。

 

syslog.conf

syslogd机制中可以通过syslog.conf对log进行管理配置。默认存放在etc目录下。当然,也可以通过initrc进行动态设置。

设置syslog.conf必须按照形式:

facility.priority            action

例如:

user.debug             /var/log/log.debug

将openlog第二个参数为LOG_USER,syslog第一个参数为LOG_DEBUG的所有信息存放到/var/log/log.debug文件中。

  • priority有:

alert、crit、debug、emerg、err、error、info、none、notice、panic、warn、warning

  • facility有:

auth、authpriv、cron、daemon、ftp、kern、mail、lpr、mark、news、security、syslog、user、uucp、local0~ local7

举例:

mail.info         /var/log/mail.log
auth.=info        @10.1.1.1 
user.!=error      /var/log/user.log
*.info           /var/log/log.info

第一行表示,mail用户的info级别的信息存放在/var/log/mail.log文件中;
第二行表示,auth(安全相关)用户的info级别的信息记录到服务器10.1.1.1上;前提是该服务器能接受到信息;
第三行表示,user用户非error级别的信息都存放在/var/log/user.log中;
第四行表示,任何用户的info级别的信息都存放在/var/log/log.info中;

 

读取log

syslogd中提供了很多种获取log 的方式,其中一种就是共享内存。当syslogd获取到log信息的时候,会通过log_to_shmem()将buf传入共享内存,用于其他的进程读取:

	if (new_tail < G.shbuf->size) {
		/* store message, set new tail */
		memcpy(G.shbuf->data + old_tail, msg, len);
		G.shbuf->tail = new_tail;
	} else {
		/* k == available buffer space ahead of old tail */
		int k = G.shbuf->size - old_tail;
		/* copy what fits to the end of buffer, and repeat */
		memcpy(G.shbuf->data + old_tail, msg, k);
		msg += k;
		len -= k;
		G.shbuf->tail = 0;
		goto again;
	}

在另外的进程中通过shmat进行获取:

	/* Attach shared memory to our char* */
	shbuf = shmat(log_shmid, NULL, SHM_RDONLY);
	if (shbuf == NULL)
		bb_perror_msg_and_die("can't %s syslogd buffer", "access");

将拿到的shbuf进行处理,例如输出到stdout中。

需要注意的是:syslogd中要求local和ipc是互斥的,所以想要log既能保存到本地log文件,又能通过共享内存方式读取,需要更改代码。

 

logread.c

在busybox中提供了通过共享内存方式进行读取log的程序logread.c,可以将syslogd共享内存中的log输出到stdout中。

将CONFIG_LOGREAD打开就可以编译出来,默认放置在sbin目录下,运行命令:

./sbin/logread –f

 

 

 

 

 

 

 

 

 

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-27
  • 2021-12-09
  • 2022-01-03
  • 2021-09-25
猜你喜欢
  • 2022-12-23
  • 2021-09-10
  • 2022-02-05
  • 2022-12-23
  • 2022-12-23
  • 2022-01-01
  • 2021-08-29
相关资源
相似解决方案