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