背景:需求来自于一个客户想将服务器的日志转发到自己的日志服务器上,所以希望我们能提供这个转发的功能,同时还要满足syslog协议。

1 什么是syslog服务

1.1 syslog标准协议如下图

这里的facility为模块,serverity为等级,由这两个信息共同计算出一个PRI头部。HEADER部分包含了时间和主机名。在HEADER和MSG之间有一个空格,MSG是需要记录的日志部分(日志消息体)。

  这里也就是说,理论上使用这种格式构造的字符串发送,接收方就能解析出来。实际上根据实验,我使用了UDP发送,接收方syslog日志服务器能正确解析。

这里需要注意的是,如果使用了程序的库,比如:python的syslog库(同样c++也有相似的库),那么就不再需要关注PRI和HEADER部分,只要将相关的参数(facility,severity,time,ip)传入函数,调用发送就可以,不必自己构造字符串。对服务端来说,接收到的是整个消息,但通常来讲,比如使用linux默认的rsyslog作为接收服务端的话,是不能看到除MSG之外的部分。

1.2 syslog服务的详细讲解

Priority(优先级) = facility * 8 + severity值。比如说,一个核心信息(facility=0)和一个Emergency的severity将会产生优先级为0。同样, 一个"local use 4"信息(facility=20)和一个Notice的severity(severity=5)将会产生165的优先级。

标题(HEADER)部分由称为TIMESTAMP和HOSTNAME的两个域组成,PRI结尾的">"会马上跟着一个 TIMESTAMP,任何一个TIMESTAMP或者HOSTNAME域后面都必须跟着一个空格字符。HOSTNAME包含主机的名称,若无主机名或无法 识别则显示IP地址。如果一个主机有多个IP地址,它通常会使用它传送信息的那个IP地址。TIMESTAMP是本机时间,采用的格式是"Mmm dd hh:mm:ss"表示月日时分秒。HOSTNAME域仅仅能够包括主机名称,Ipv4地址或者是信息产生者的Ipv6地址。

MSG部分是Syslog数据包剩下的部分。这通常包含了产生信息进程的额外信息,以及信息的文本部分。MSG部分有两个域,分别为TAG域和 CONTENT域,TAG域的值是产生信息的程序或者进程的名称,CONTENT包含了这个信息的详细内容。传统上来说,这个域的格式较为自由,并且给出 一些时间的具体信息。TAG是一个不许超过32个字符的字母数字字符串,任何一个非字母数字字符都将会终止TAG域,并且被假设是CONTENT域的开 始。在大多数情况下,表示TAG结束的CONTENT域的第一个字符用左大括号( [ ],分号( : )或者是空格来表示

1.3 Syslog库

以python的库为例:

  openlog(ident[, logopt[, facility]])

首先需要使用openlog指定模块及相应的信息。ident为头部需要显示的字符串,这个信息不包含在MSG中,可以通过配置日志服务器模板决定是否显示。logopt是一些参数,可选择有(LOG_PID, LOG_CONS, LOG_NDELAY, LOG_NOWAIT and LOG_PERROR),对应的分别是(包括每个消息PID,直接写入系统控制台,立即打开连接,不等待子进程(因为其有可能在记录消息的时候就被创建了,GNU C库不创建子进程,所以该选项在Linux上没有影响),同时输出到stderr)。facility则是模块参数,需要填入对应的值,这里syslog库中有以下参数使用:

LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON, LOG_AUTH, LOG_LPR

LOG_NEWS, LOG_UUCP, LOG_CRON and LOG_LOCAL0 to LOG_LOCAL7

通常来说,openlog需要在模块最开始指定,即限定了这个模块内都是一个facility的日志。

  syslog([sevirity], msg):

  这个是具体打印日志的函数,第一个参数指定消息的级别,第二个参数为日志内容。

sevirity对应的参数为:

LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING,
LOG_NOTICE, LOG_INFO, LOG_DEBUG.

closelog():这个是关闭的功能

2 了解rsyslog服务

rsyslog配置文件/etc/rsyslog.conf大概分为三个部分

2.1 #MODULES

  这个部分是针对接收配置的,主要是指定接收日志的协议和端口。若要配置日志服务器,则需要将相应的配置项去掉注释。

2.2 #GLOBAL DIRECTIVES

这个部分主要用来配置模板,模板的作用是指定你希望在日志文件中保存的日志格式。

默认配置为:

# Use default timestamp format

$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat

列举一个模板,将所有信息保存:

# 这里第一行(为了方便显示,参数写成了一列)是模板,即日志服务器记录到日志文件的格式

# 第二行是指定需要使用的模板myFormat,这个名字可以自己定义

$template myFormat,"%TIMESTAMP% host=%HOSTNAME%,

                   relayHost=%FROMHOST%,

                   tag=%syslogtag%,

                   programName=%programname%,

procid=%PROCID%,

facility=%syslogfacility-text%,

sev=%syslogseverity-text%,

appName=%APP-NAME%,

msg=%msg%"

$ActionFileDefaultTemplate myFormat

模板额外说明:

#在rsyslog7 和更高版本使用以下格式:

template(name="scalaLogFormat" type="list") {

property(name="timestamp" dateFormat="rfc3339")

constant(value=" host=")

property(name="hostname")

constant(value=", relayHost=")

property(name="fromhost")

constant(value=", tag=")

property(name="syslogtag")

constant(value=", programName=")

property(name="programname")

constant(value=", procid=")

property(name="procid")

constant(value=", facility=")

property(name="syslogfacility-text")

constant(value=", sev=")

property(name="syslogseverity-text")

constant(value=", appName=")

property(name="app-name")

constant(value=", msg=")

property(name="msg" )

constant(value="")

2.3 #begin forwarding rule

这个模块主要讲一下转发

  #*.* @@remote-host:514

  根据这个实例可以看出,分为4个部分[模块.等级] [转发协议][日志服务器地址]:[日志服务器端口],其中转发协议的参数@@为TCP协议,对应的接收端也需要配置接受TCP协议。@为UDP协议。

  注:使用TCP协议,若地址错误或不能连同的情况,转发的协议会写入缓存,但是不用担心会卡死服务器,当到达一定限度后会自动转存到硬盘,这个不是我们应该关心的部分,使用就好了。

说明:

  针对rsyslog.conf配置文件的所有操作都需要重启服务生效(service rsyslog restart)

  在新版本的rsyslog中,对日志发送有默认限速,如果有集中大量推送日志的情况,需要在配置文件中加上参数$SystemLogRateLimitInterval 0(具体位置没有影响,但通常写在GLOBAL DIRECTIVES模块)

  通常来说,日志推送到服务器的协议使用UDP

3 实例演示转发日志模块

使用TCP/UDP通信,自己构造syslog消息发送

首先了解syslog协议,及接受的方式,自己使用网络编程实现转发日志变成了可能,下面介绍syslog接受原理

接受端服务器收到发送给它的syslog数据包,它将检查它的有效PRI。如果第一次字符不是一个"",接收端将认为数据包没有包含有效的PRI。接着检查在标题部分的有效TIMESTAMP,从这些规则中,信息的接收一般有三个情况,下面给 出了这三个情况的通常属性,并列举了随后在这篇中什么地方会描写这些情况。

有效的PRI and TIMESTAMP:在数据包中发现一个有效的PRI和TIMESTAMP,那么会接着检查数据包的内部配置,接收端必须根据数据包的优先级来还原,或者 在不对数据包做任何变化的情况下将它转发出去。这里要注意到的是接受端没有必要确认TIMSTIMP里面的时间,同时接收端也没有必要确认 HOSTANME的值和发送信息设备的主机名或者IP地址一致。

有效的 PRI,但没有TIMESTAMP 或者TIMESTAMP无效:要是在数据包中发现一个有效的TIMESTAMP,那么必须马上添加一个TIMESTAMP和一个空格字符在PRI部分的结 尾的方括号内,它还必须添加一个HOSTNAME和空格字符在TIMESTAMP后面,接收到的信息包剩下的部分必须被当曾MSG的CONTENT域并附 加上,由于无法识别产生信息的设备所发出的进程,TAG的值无法被识别出来, 所以不会包含再里面。TIMESTAMP将会是接收端的本地时间,HOSTNAME是设备的名称,它被中继器所识别。如果名字如能被决定, 设备的IP地址将被使用到。要是中继器添加一个TIMESTAMP(或者同时添加TIMESTAMP和HOSTNAME)在PRI后面, 然后检 查是否数据包的总体长度仍然小于或等于1024个字节。如果数据包被扩展超过1024个比特, 中继器必须截去一部分数据包数据使它到达到1024比特。这将会导致原始数据包结尾部分重要信息的丢失. 所以,这就是产生的syslog数据包的PRI和HEADER部分包含在4.3节所记录的值和域之中的缘故。

没有 PRI or 或者 PRI无法识别:如果收不到PRI或者PRI不可识别,除了必须插入一个优先级为13的PRI和我们在上面描述的TIMESTAMP,还必须插入一个 HOSTNAME。被接收到的数据包的全部内容将被认为是被传递的MSG的CONTENT并被添加在后面。一个不可识别的PRI的例子就是"< 00>",这也许是一个信息的前4个字符。如果接收到这样的syslog信息,那么它的优先级将被中继器或收集者改为13,并且加入 TIMESTAMP。具体如下:

原来接收到的信息

  <00>...

  被传递或识别的信息

  <13>TIMESTAMP HOSTNAME <00>...

  如果中继器添加一个TIMESTAMP(或者同时添加一个TIMESTAMP和HOSTNAME)在PRI后面, 那么它将检查这个数据包的总体长度是否等于或者小于1024个比特。

  在UNIX文件系统里头,syslog设备依据两个重要的文件:syslogd(守护进程)和syslog.conf配置文件。习惯上,多数syslog 信息被写到/var/adm或/var/log目录下的信息文件中(syslog或messages.*)。一个典型的syslog纪录包括生成程序的名 字和一个文本信息。它还包括一个设备和一个优先级范围(但不在日志中出现)。Syslog.conf的格式比较复杂,大家可以参考一下有关书籍(或者在主 机上man syslog.conf),主要是如下语句形式: facility、level、action。Facility代表各种服务,level代表syslog的认证级别,action代表的是针对前面信息 的处理动作。Action字段如果是@loghos(主机名或具体IP),则把信息发送到loghost,而不是本地的 /var/adm/messages。

syslog函数输出在哪个文件中_syslog服务详解相关推荐

  1. FLV文件中VideoPacket的详解

    FLV文件中VideoPacket的详解 众所周知,FLV文件体主要有三种Tag组成:AUDIODATA.VIDEODATA和SCRIPTDATA,其中SCRIPTDATA中包含了MetaData,通 ...

  2. NT的BOOT.INI文件中ARC命名详解(转)

    NT的BOOT.INI文件中ARC命名详解(转)[@more@] ARC命名是Windows NT系统用来定位其引导分区所在的路径,也就是利用它指明引导分区在哪一个磁盘控制器,哪一个硬盘,哪一个分区内 ...

  3. Linux日志系统_syslog服务详解

    Linux日志系统_syslog服务详解 参考链接:https://blog.csdn.net/weixin_42569329/article/details/116609984 一台服务器的日志对系 ...

  4. spark输出rdd数据_Spark中RDD的详解

    (collect 收集 //将rdd分布式存储在集群中不同分区的数据 获取到一起 组成一个数组返回 //要注意 这个方法将会把所有数据搞到一个机器内 容易造成内存的溢出 在生产环境下千万慎用 rdd. ...

  5. Android.mk文件中的内容详解

    一.简介 在官网对 Android.mk 的介绍中写道: Android.mk 文件位于项目 jni/ 目录的子目录中,用于向构建系统描述源文件和共享库. 二.基础知识 这里介绍一些Android.m ...

  6. 数据库控制文件中的SCN详解

    在的启动和关闭数据库的时候控制文件起着重要的作用,从官方文档中我们可以知道控制 文件中保存着下列的信息: 数据库的名称及数据库创建时间等 所有的数据文件.重做日志文件的名称和位置信息. 表空间的信息. ...

  7. android中service名词解释,Android中Service(服务)详解

    A service is "bound" when an application component binds to it by calling 通过startService() ...

  8. python文件读取输出-python分批定量读取文件内容,输出到不同文件中的方法

    一.文件内容的分发 应用场景:分批读取共有358086行内容的txt文件,每取1000条输出到一个文件当中 # coding=utf-8 # 分批读取共有358086行内容的txt文件,每取1000条 ...

  9. 将函数实现放在头文件中

    研究一个开源算法库,采用C++模板编程,所有函数实现都放在了头文件中,现在把模板去掉,链接时发生冲突,具体原因如下: 因为多个源文件包含了含有函数定义的头文件,在编译的时候,每个源文件都会包含一份函数 ...

  10. System.out. 输出到指定文件中

    用下面的方法,就可以输出到指定文件中了 String strJSON = "这是一段字符串,这段字符串将会打印到指定文件中."; //日志输出到指定文件中 PrintStream ...

最新文章

  1. 立下“去O”Flag的AWS,悄悄修炼了哪些内功?
  2. Otter-入门篇4(单向同步实践)
  3. 计算机应用基础 实验指导,计算机应用基础实验指导EXCEL
  4. 【Hibernate】hibernate主键生成策略与配置详解
  5. How to ignore files and directories in subversion?
  6. mysql 别名 metadata_获取数据库元数据:DatabaseMetaData与ParameterMetaData与ResultSetMetaData...
  7. SpringBoot2 整合 XFIRE 服务端和客户端
  8. OJ1010: 求圆的周长和面积
  9. LeetCode 题 - 35. 搜索插入位置
  10. 微积分经典概念:极限、连续与函数
  11. MeasureSpec
  12. 卡尔曼滤波-卡尔曼滤波全篇讲解
  13. 计算机硬盘从桌面消失了,如何解决win10硬盘分区不见了_win10机械硬盘突然消失解决方法...
  14. IO操作中flush()方法作用
  15. 浅谈游戏数据分析------留存篇一---留存折损
  16. 亚马逊程序员:我曾拼命逃离996!
  17. Q for Mortals2笔记 -- 概述
  18. 水利工程资料用什么软件
  19. 微信的发展堪称疯狂,这 7 点值得所有人学习|投资人说-20170504早读课
  20. python统计txt文件中不同文字出现的次数_Python统计文本词汇出现次数的实例代码...

热门文章

  1. 新任项目经理的五项必修课 (转)
  2. ListView,GridView的getView多次调用问题
  3. python cls参数_python cls self 讲解
  4. vc屏幕录像存为wmv文件_最好用的录像软件,三步实现高清录制?
  5. node.js 与 nvm安装教程
  6. python计算出nan_学习笔记0522:Tensorflow训练模型出现loss是nan的问题排查
  7. ThinkPhp项目部署到Linux file_put_contents() 报错:failed to open stream: Permission denied
  8. MySQL数据库将多条记录的单个字段合并成一条记录(GROUP_CONCAT)
  9. PHP 保留 n 位小数
  10. 文字处理技术:文字形状绕排不是挺简单的事吗,怎么搞得这么复杂