洞察探索open banking如何通过小程序容器技术助力金融企业实现数据安全和数字化转型
1009
2022-09-24
syslog的点滴--集中处理日志
syslogd和klogd是很有意思的守护进程,syslogd是一个分发器,它将接收到的所有日志按照/etc/syslog.conf的配置策略发送到这些日志应该去的地方,当然也包括从klogd接收到的日志,klogd首先接收内核的日志,然后将之发送给syslogd,klogd是怎么接收内核的日志,接收到的日志又是怎么发给syslogd的呢?过程其实很简单,klogd通过读取/proc/kmsg来接收内核的日志,通过strace -p可以看到: read(0, "<6>ACPI: PCI interrupt 0000:05:0"..., 4095) = 95 time([1278013550]) = 1278013550 write(1, "<6>Jul 1 15:45:50 kernel: ACPI:"..., 97) = 97 为了看清楚0和1分别代表什么,看一下/proc文件系统: ll /proc/XX/fd/ total 3 lr-x------ 1 root root 64 2010-07-01 15:43 0 -> /proc/kmsg lrwx------ 1 root root 64 2010-07-01 15:43 1 -> socket:[7974] lr-x------ 1 root root 64 2010-07-01 15:43 2 -> /boot/System.map... 或者通过lsof -p XX查看也是可以的。经过解析命令的输出,发现klogd从/proc/kmsg中读取了内核信息,然后写入了一个套接字,这个套接字的另一端肯定是syslogd使用的套接字,并且syslogd肯定从该套接字的另一端接收了数据,用strace和lsof/ll /proc/YY/fd/证实一下: ll /proc/YY/fd total 18 lrwx------ 1 root root 64 2010-07-01 15:21 0 -> socket:[4146] l-wx------ 1 root root 64 2010-07-01 15:21 1 -> /var/log/auth.log ... l-wx------ 1 root root 64 2010-07-01 15:21 8 -> /var/log/uucp.log l-wx------ 1 root root 64 2010-07-01 15:21 9 -> /var/log/mail.info 确实是这样的,syslogd中确实使用了一个套接字,为了证实确实从该套接字接收到了klogd发来的数据,在两个终端上同时strace -p syslogd和klogd,然后加载一个驱动或者自己写一个printk的内核模块,然后观察两个终端的输出,确实klogd从0读出了信息abc,然后写入了1,syslogd从0读出了abc,然后写入了一个配置好的日志文件,它们之间是通过套接字来完成通信的。同样的,库函数syslog将klogd的大致过程进行了封装,这样任何程序都可以调用syslog函数进行日志记录了,syslogd成了整个系统统一的一个日志记录器,下面是在syslog的manpage上得到的函数原型: void openlog(const char *ident, int option, int facility); //ident设置为一个可被过滤的特征字符串,一般为应用程序的名字 void syslog(int priority, const char *format, ...); void closelog(void); 此处的syslog库函数内部实现的就是套接字发送过程,没有什么好说的,可是千万不要将这个syslog和linux的系统调用sys_syslog搞混淆了,后者的原型是: asmlinkage long sys_syslog(int type, char __user *buf, int len); 而dmesg调用的正是这个函数,该函数内部通过type分成了若干个类型,其实klogd也是可以通过直接调用这个函数来实现的(/proc/kmsg的read方法就是调用do_syslog,而sys_syslog也是调用do_syslog)。 syslogd和syslog库函数中使用的套接字就是unix族套接字,是unix本地进程间通信的一种好办法,这种套接字必须有一对,本质上实现了一个管道,在接口和语义上又和bsd套接字相统一,实际上bsd套接字没有网络的概念,它只承认自己可以实现进程间通信,它将网络通信也统一看作了进程间通信,只是后来的AF_INET等实现的不同机器间的进程间通信,而原始的AF_UNIX实现的是本机的进程间通信。既然AF_UNIX实现了本机的进程间通信,那么它的地址只需要本机内唯一即可,因此采用普通文件是一个不错的选择,其地址就是文件的全路径: struct sockaddr_un { sa_family_t sun_family; char sun_path[UNIX_PATH_MAX]; //文件路径 }; 比如syslogd使用的/dev/log就是一个处于一般文件系统的套接字。套接字创建函数socket的第二个参数是类型,AF_UNIX族的套接字也分stream类型和datagram类型,只是在语义约束上松了很多,datagram仅仅在数据边界等不多的方面和stream类型的套接字有区别,有无连接的概念已经退化了。不管是stream还是datagram类型的AF_UNIX套接字,send的本质就是将数据放入接收者的接收队列,recv则相反。 上述套接字和管道的区别是什么?仅仅是使用时的语义不同,管道的约束很少,也不很规范,很难扩展,而套接字拥有地址空间的概念,有协议的概念,很容易进行扩展,并且语义也很清晰。也正是这种统一,使得syslog很容易支持远程日志记录,本机日志记录和远程记录都使用套接字,所不同的只是套接字的地址族不同,这样很多编码都可以参数化,配置化,不必再写冗余的代码了。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~