rsyslog入门


配置rsyslog日志_syslog强大而安全的日志处理系统

安装

apt-get install rsyslog -y

查看版本

rsyslogd -v

查看状态

systemctl status rsyslog

重新启动

 systemctl restart rsyslog

配置Rsyslog服务端

vim /etc/rsyslog.conf

取消这几行前面的注释,同事使用UDP和TCP协议的514端口

$ModLoad imudp
$UDPServerRun 514
$ModLoad imtcp
$InputTCPServerRun 514

指定子网、IP或域名来限制访问,如下所示:

$AllowedSender TCP, 127.0.0.1, 192.168.0.0/24, *.example.com
$AllowedSender UDP, 127.0.0.1, 192.168.0.0/24, *.example.com

创建一个模板来告诉Rsyslog如何存储传入的syslog消息。在GLOBAL DIRECTIVES部分之前添加以下几行:

$template remote-incoming-logs,"/var/log/%HOSTNAME%/%PROGRAMNAME%.log" 
*.* ?remote-incoming-logs

用以下命令检查Rsyslog配置信息是否有语法错误:

linuxprobe@ubuntu-18-04-lts:~$ rsyslogd -f /etc/rsyslog.conf -N1
rsyslogd: version 8.32.0, config validation run (level 1), master config /etc/rsyslog.conf
rsyslogd: End of config validation run. Bye.

配置Rsyslog客户端

配置Rsyslog客户端来向远程服务端发送系统日志消息。登录客户端,打开/etc/rsyslog.conf添加如下信息:

linuxprobe@ubuntu-18-04-lts:~$ vim /etc/rsyslog.conf
##Enable sending of logs over UDP add the following line:
 
*.* @192.168.0.101:514
 
 
##Enable sending of logs over TCP add the following line:
 
*.* @@192.168.0.101:514
 
##Set disk queue when rsyslog server will be down:
 
$ActionQueueFileName queue
$ActionQueueMaxDiskSpace 1g
$ActionQueueSaveOnShutdown on
$ActionQueueType LinkedList
$ActionResumeRetryCount -1

重新启动Rsyslog:

linuxprobe@ubuntu-18-04-lts:~$ systemtcl restart rsyslog 

查看日志

此时,Rsyslog客户端被配置为将它们的日志发送到Rsyslog服务端。
现在,登录到Rsyslog服务器并检查/var/log目录。看到客户端机器的主机名,包括几个日志文件

ls /var/log/rsyslog-client/
CRON.log  kernel.log  rsyslogd-2039.log  rsyslogd.log  sudo.log  wpa_supplicant.log

 

 

docker容器中使用rsyslogd

rsyslogd作为CentOS:7系统自带的日志管理工具,为很多服务提供了便捷的日志管理接入方案,然而 CentOS:7的官方镜像 默认是不支持rsyslogd的。我们做个实验:

1)启动测试容器

docker run -it --name=test-syslog centos:7 /bin/bash

2)安装rsyslogd

yum -y install rsyslog

3)测试rsyslogd

rsyslogd  # 启动日志服务
logger "Hello rsyslog"  # 发送一条日志
cat /var/log/messages  # 查看日志内容

我们可以看到并没有任何输出。

4)分析原因

原因比较简单,即rsyslog默认通过 journal 读取日志信息,但CentOS镜像默认并未安装systemd和journald。有两个解决方案:

(1)按官方提供的教程(systemd integration)将systemd和journald集成到CentOS:7镜像里;

(2)修改 rsyslogd 的配置,不经过 journal 读取日志信息。这里讲解下方案(2)的具体操作。

5)修改配置

cat /var/run/syslogd.pid  # 查看刚才启动的rsyslogd进程pid
kill -9 进程号  # 将刚才启动的rsyslogd关掉
rm -rf /etc/rsyslog.d/listen.conf  # 将 journal 的配置删除

vi 打开 /etc/rsyslog.conf 文件,将 $ModLoad imjournal 和 $IMJournalStateFile imjournal.state 这两行注释;将 $OmitLocalLogging on 改为 $OmitLocalLogging off。保存退出。

6)测试验证

rsyslogd  # 启动日志服务
logger "Hello rsyslog"  # 发送一条日志
cat /var/log/messages  # 查看日志内容

可以看到如下输出,说明日志服务已正常:

May 21 08:57:54 60c66cdf443f rsyslogd:  [origin software="rsyslogd" swVersion="8.24.0-34.el7" x-pid="108" x-info="http://www.rsyslog.com"] start
May 21 08:58:05 60c66cdf443f root: Hello rsyslog

 

 

用python socket发送rsyslog日志

  • 原文地址:https://blog.csdn.net/safenli/article/details/75452741

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 socket

s = 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 e
setSock.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 socket
import cPickle
import struct
s = 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:
    pass
setSock.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 StringIO
except ImportError:
    from StringIO import StringIO
import socket

s = 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:
    pass
setSock.close()

从上面源码可以发现,它发送的是一个ASCII流。但是为什么要添加那么多的V,P还有换行符呢?
(3)从上面我发现了一个重点raw-unicode-escape,感觉这个东东肯定是重点,然后就把传入的字符串都转换成这个格式试试,结果失望。参考了这个,在我不断尝试中,终于发现了问题的关键,浓缩代码如下:

#!/usr/bin/env python
#-*-coding:utf-8 -*-

import socket

s = 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:
    pass
setSock.close()

我认为火眼晶晶的小伙伴们都发现了重点,就是字符串后面必须加个\n,还要用raw-unicode-escape编码,具体为啥,我也不知道。

 

rsyslog详解实战和避坑

作  者:Taosiyu
出  处:https://www.cnblogs.com/taosiyu/p/12930410.html

 

 

python logging测试

import logging
import socket
import sys
import os
from loguru import logger
from logging.handlers import SysLogHandler
import logging.handlers
from configs import LOG_FILE_DIR

LOG_FORMAT = (
    "[{time:YYYY-MM-DD HH:mm:ss.SSS}] [{level}] [{module}.{function}:{line}] {message}"
)

logger.configure(
    handlers=[
        dict(
            sink=sys.stderr,
            filter={
                "": logging.INFO,
                "app1.view": logging.ERROR,
            },
            colorize=False,
            backtrace=False,
            format=LOG_FORMAT,
        ),
        dict(
            sink=LOG_FILE_DIR / "ai.log",
            filter={
                "": False,
                "app1.view": logging.INFO,
                "app2.view": logging.INFO,
            },
            level=logging.INFO,
            colorize=False,
            backtrace=False,
            format=LOG_FORMAT,
        )
    ]
)

formatter = logging.Formatter('%(name)s: %(levelname)s %(message)r')
handler = SysLogHandler(facility=SysLogHandler.LOG_LOCAL5,
                        address=('localhost', 514),
                        socktype=socket.SOCK_STREAM)
handler.setFormatter(formatter)
logger.add(handler, level="INFO")

测试

import socket


def test_loguru():
    import logging
    from loguru import logger
    from logging.handlers import SysLogHandler

    handler = logging.handlers.SysLogHandler(facility=SysLogHandler.LOG_LOCAL5, address=('localhost', 514),
                                             socktype=socket.SOCK_STREAM)
    logger.add(handler)

    logger.debug('debug message test')  # 指明级别为debug
    logger.error('error message test')  # 指明级别为error
    logger.debug("That's it, beautiful and simple logging!")


def test_logging():
    # coding:utf-8,
    import logging
    from logging.handlers import SysLogHandler

    log = logging.getLogger('mylog')
    log.setLevel(logging.DEBUG)

    # log_hdlr = SysLogHandler(facility=SysLogHandler.LOG_LOCAL5)
    log_hdlr = SysLogHandler(facility=SysLogHandler.LOG_LOCAL5, address=("127.0.0.1", 514), socktype=socket.SOCK_STREAM)
    # log_hdlr = SysLogHandler()
    log_format = logging.Formatter(
        'hhl-%(name)s-server[%(process)d]-%(levelname)s: %(message)s')
    log_hdlr.setFormatter(log_format)
    log_hdlr.setLevel(logging.ERROR)  # 接受error及以上的日志信息
    log.addHandler(log_hdlr)
    log.debug('debug message test')  # 指明级别为debug
    log.error('error message test')  # 指明级别为error
    print("test_logging")
    # 最后只保存error及更高优先级的日志


def test_shell():
    """
    # 最后只保存error及更高优先级的日志
    # echo5*|987654321*|admin*|check*|” | nc localhost 514
    """


def socket_log():
    import socket
    import pickle

    s = u"5*|987654321*|admin*|check*|1*|加班*|datacenterid=1*|"
    s = b'<171>hhl-mylog-server[3093]-ERROR: error message test\x00'
    setSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    setSock.connect(("localhost", 514))
    cs = pickle.dumps(s)
    try:
        setSock.send(cs)
    except socket.error as e:
        pass
    setSock.close()


if __name__ == '__main__':
    test_loguru()

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM