用python socket发送rsyslog日志
来源:互联网 发布:全球网络加速器 编辑:程序博客网 时间:2024/06/05 00:46
最近做了一个项目,其中要求把日志发送给syslog服务器,客户端是用python写的,开始要求发送用UDP协议就行,简单;可后来要求改用TCP,问题就出来了,rsyslog收到日志,就是不写入指定的日志文件中,所以有必要把这其中的历程写下来。
UDP rsyslog
(1) 首先编辑/etc/rsyslog.conf,把udp注释去掉
# provides udp syslog reception$modload imudp$InputUDPServerRun 514##### template ####$template LongFileFormat,"<%PRI%>%TIMESTAMP:::date-rfc3339% %syslogpriority% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n"$template ScTemplate,"/var/log/tem.log"if $msg contains "*|" then{ *.* ?ScTemplate;LongFileFormat & stop}
(2)客户端用python socket正常发送就行
#!/usr/bin/env python#-*-coding:utf-8 -*-import sockets = u"5*|987654321*|admin*|check*|1*|加班*|datacenterid=1*|"setSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)try: setSock.sendto(s,(HOST, 514))except socket.error, e: print esetSock.close()
TCP syslog
这个才是重中之重,开始我只是按照上面的配置方法把相应的udp改成tcp,我以为就完事了,谁想….客户端用socket的tcp把数据成功发送出去了,服务器端的514也改成tcp协议了,selinux,iptables等都放开了,用tcpdump监听514端口,也收到数据了,但是,就是不写到日志文件里。
#创建/etc/rsyslog.d/tcp.conf文件,内容如下# provides tcp syslog reception$modload imtcp$InputTCPServerRun 514##### template ####$template LongFileFormat,"<%PRI%>%TIMESTAMP:::date-rfc3339% %syslogpriority% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n"$template ScTemplate,"/var/log/tem.log"if $msg contains "*|" then{ *.* ?ScTemplate;LongFileFormat & stop}
后来我用echo “5*|987654321*|admin*|check*|” | nc host port命令模拟发送syslog日志时,syslog竟然写入到日志文件里了。这时初步判定,问题在发送方,即python socket tcp。
(1)我用模块logging发送syslog日志时,偶尔也能成功,所以我就决定看一下这个logging发送tcp的原理,找到如下,浓缩版:
#!/usr/bin/env python#-*-coding:utf-8 -*-import socketimport cPickleimport structs = u"5*|987654321*|admin*|check*|1*|加班*|datacenterid=1*|"setSock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)setSock.connect((HOST, 514))cs = cPickle.dumps(s)#slen = struct.pack(">L", 2)try: setSock.send(slen + cs)except socket.error, e: passsetSock.close()
从上面的代码中我们可以定位到logging模块用了两个关键的处理cPickle.dumps和struct.pack,后来发现struct.pack没啥特别大的用。因为我发送的是字符串,如果是字典的话用处就大了。
(2)但是这个发送时,syslog接收的日志开头会莫名的多出一个大写V。后来知道如果被传入字符串是unicode时会是V,utf-8时是S。为了去掉这个多余难看的V,我又看了cPickle模块的源码,原理浓缩如下:
#!/usr/bin/env python#-*-coding:utf-8 -*-try: from cStringIO import StringIOexcept ImportError: from StringIO import StringIOimport sockets = u"5*|987654321*|admin*|check*|1*|加班*|datacenterid=1*|"def dumps(obj): fd = StringIO() obj = obj.replace("\\", "\\u005c") obj = obj.replace("\n", "\\u000a") fd.write('V' + obj.encode('raw-unicode-escape') + '\n') fd.write('p' + repr(0) + '\n') fd.write('.') return fd.getvalue()ss = dumps(a)setSock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)setSock.connect((HOST,514))try: setSock.send(ss)except (AttributeError,socket.error), e: passsetSock.close()
从上面源码可以发现,它发送的是一个ASCII流。但是为什么要添加那么多的V,P还有换行符呢?
(3)从上面我发现了一个重点raw-unicode-escape,感觉这个东东肯定是重点,然后就把传入的字符串都转换成这个格式试试,结果失望。参考了这个,在我不断尝试中,终于发现了问题的关键,浓缩代码如下:
#!/usr/bin/env python#-*-coding:utf-8 -*-import sockets = u"5*|987654321*|admin*|check*|1*|加班*|datacenterid=1*|"setSock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)setSock.connect((HOST,514))ss = (s + '\n').encode('raw-unicode-escape')try: setSock.send(ss)except (AttributeError,socket.error), e: passsetSock.close()
我认为火眼晶晶的小伙伴们都发现了重点,就是字符串后面必须加个\n,还要用raw-unicode-escape编码,具体为啥,我也不知道。
- 用python socket发送rsyslog日志
- 使用java向rsyslog发送日志
- Flume采集rsyslog发送的audit日志
- nginx 1.4.7 发送日志到rsyslog
- rsyslog日志服务器的配置步骤( 远程发送日志 )
- rsyslog 直接kill进程,在重新启动会全部发送日志
- 详解rsyslog/Python/LogAnalyzer 记录和查看服务端/客户端日志
- python socket发送数字
- rsyslog 直接读取日志,当日志截断后,不会继续发送
- Rsyslog 日志服务器
- 日志服务器Rsyslog
- rsyslog日志系统
- rsyslog 传输日志
- rsyslog 传输mysql 日志
- rsyslog 日志服务器端配置
- rsyslog 收集系统日志
- rsyslog收集网络设备日志
- 集中日志服务器Rsyslog
- 【剑指offer】面试题17:打印从1到最大的n位数
- 【SVN】中检出(check out) 和导出(export) 的区别
- 如何理解spring
- 删除文件夹下的所有文件和子文件夹
- I/O多路复用之epoll
- 用python socket发送rsyslog日志
- SPOJ VLATTICE Visible Lattice Points 莫比乌兹反演入门题
- git版本回退
- [python]解析通达信盘后数据获取历史日线数据
- POJ_1808_Quadratic Residues
- SSM项目开发环境配置(一)
- HDU 2157 How many ways?? (矩阵快速幂)
- 赣江源头“警色”美
- JFinal+Quartz动态任务调度控制台