如何在 Python 中将日志配置为 syslog?

我无法理解巨蟒的 logging模块。我的需求非常简单: 我只想把所有东西都记录到 syslog 中。在阅读了文档之后,我想出了这个简单的测试脚本:

import logging
import logging.handlers


my_logger = logging.getLogger('MyLogger')
my_logger.setLevel(logging.DEBUG)


handler = logging.handlers.SysLogHandler()


my_logger.addHandler(handler)


my_logger.debug('this is debug')
my_logger.critical('this is critical')

但是这个脚本在 syslog 中没有产生任何日志记录?

182958 次浏览

是否设置了 syblog.conf 来处理 Facility = user?

您可以使用工具参数设置 python 日志记录器使用的工具,如下所示:

handler = logging.handlers.SysLogHandler(facility=SysLogHandler.LOG_DAEMON)

把这句话改成:

handler = SysLogHandler(address='/dev/log')

这对我有用

import logging
import logging.handlers


my_logger = logging.getLogger('MyLogger')
my_logger.setLevel(logging.DEBUG)


handler = logging.handlers.SysLogHandler(address = '/dev/log')


my_logger.addHandler(handler)


my_logger.debug('this is debug')
my_logger.critical('this is critical')

我添加了一个小额外的评论,以防它帮助任何人,因为我发现这个交流很有用,但需要这个小额外的信息让它全部工作。

要使用 SysLogHandler 记录到特定工具,您需要指定工具值。 举个例子,你定义了:

local3.* /var/log/mylog

在 syslog 中,那么您将要使用:

handler = logging.handlers.SysLogHandler(address = ('localhost',514), facility=19)

而且您还需要让 syslog 监听 UDP,以使用 localhost 代替/dev/log。

import syslog
syslog.openlog(ident="LOG_IDENTIFIER",logoption=syslog.LOG_PID, facility=syslog.LOG_LOCAL0)
syslog.syslog('Log processing initiated...')

上面的脚本将使用我们的自定义“ LOG _ IDENTIFIER”登录到 LOCAL0设施..。 你可以使用 LOCAL [0-7]作本地用途。

您应该使用本地主机进行日志记录,无论是/dev/log 还是通过 TCP 堆栈进行本地主机记录。这允许完全 RFC 兼容和功能齐全的系统日志守护进程处理 syslog。这消除了远程守护进程的功能需求,并提供了 syslog 守护进程的增强功能,例如 rsyslog 和 syslog-ng。SMTP 的原理也是一样的。交给本地 SMTP 软件就行了。在这种情况下,使用“程序模式”不是守护进程,而是相同的思想。让更有能力的软件来处理它。重试、排队、本地假脱机、对 syslog 使用 TCP 而不是 UDP 等等都成为可能。您还可以根据需要分别[重新]配置这些守护进程。

将您的代码保存到您的应用程序中,让其他软件一起完成它的工作。

来自 https://github.com/luismartingil/per.scripts/tree/master/python_syslog

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


'''
Implements a new handler for the logging module which uses the pure syslog python module.


@author:  Luis Martin Gil
@year: 2013
'''
import logging
import syslog


class SysLogLibHandler(logging.Handler):
"""A logging handler that emits messages to syslog.syslog."""
FACILITY = [syslog.LOG_LOCAL0,
syslog.LOG_LOCAL1,
syslog.LOG_LOCAL2,
syslog.LOG_LOCAL3,
syslog.LOG_LOCAL4,
syslog.LOG_LOCAL5,
syslog.LOG_LOCAL6,
syslog.LOG_LOCAL7]
def __init__(self, n):
""" Pre. (0 <= n <= 7) """
try:
syslog.openlog(logoption=syslog.LOG_PID, facility=self.FACILITY[n])
except Exception , err:
try:
syslog.openlog(syslog.LOG_PID, self.FACILITY[n])
except Exception, err:
try:
syslog.openlog('my_ident', syslog.LOG_PID, self.FACILITY[n])
except:
raise
# We got it
logging.Handler.__init__(self)


def emit(self, record):
syslog.syslog(self.format(record))


if __name__ == '__main__':
""" Lets play with the log class. """
# Some variables we need
_id = 'myproj_v2.0'
logStr = 'debug'
logFacilityLocalN = 1


# Defines a logging level and logging format based on a given string key.
LOG_ATTR = {'debug': (logging.DEBUG,
_id + ' %(levelname)-9s %(name)-15s %(threadName)-14s +%(lineno)-4d %(message)s'),
'info': (logging.INFO,
_id + ' %(levelname)-9s %(message)s'),
'warning': (logging.WARNING,
_id + ' %(levelname)-9s %(message)s'),
'error': (logging.ERROR,
_id + ' %(levelname)-9s %(message)s'),
'critical': (logging.CRITICAL,
_id + ' %(levelname)-9s %(message)s')}
loglevel, logformat = LOG_ATTR[logStr]


# Configuring the logger
logger = logging.getLogger()
logger.setLevel(loglevel)


# Clearing previous logs
logger.handlers = []


# Setting formaters and adding handlers.
formatter = logging.Formatter(logformat)
handlers = []
handlers.append(SysLogLibHandler(logFacilityLocalN))
for h in handlers:
h.setFormatter(formatter)
logger.addHandler(h)


# Yep!
logging.debug('test debug')
logging.info('test info')
logging.warning('test warning')
logging.error('test error')
logging.critical('test critical')

把这里和其他地方的东西拼凑在一起,这是我想出来的可以在 ubuntu 12.04和 centOS6上工作的东西

/etc/rsyslog.d/中创建一个以. conf 结尾的文件,并添加以下文本

local6.*        /var/log/my-logfile

重新启动 rsyslog,重新加载似乎不适用于新的日志文件。也许它只重新加载现有的 conf 文件?

sudo restart rsyslog

然后您可以使用这个测试程序来确保它实际工作。

import logging, sys
from logging import config


LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '%(levelname)s %(module)s P%(process)d T%(thread)d %(message)s'
},
},
'handlers': {
'stdout': {
'class': 'logging.StreamHandler',
'stream': sys.stdout,
'formatter': 'verbose',
},
'sys-logger6': {
'class': 'logging.handlers.SysLogHandler',
'address': '/dev/log',
'facility': "local6",
'formatter': 'verbose',
},
},
'loggers': {
'my-logger': {
'handlers': ['sys-logger6','stdout'],
'level': logging.DEBUG,
'propagate': True,
},
}
}


config.dictConfig(LOGGING)




logger = logging.getLogger("my-logger")


logger.debug("Debug")
logger.info("Info")
logger.warn("Warn")
logger.error("Error")
logger.critical("Critical")

还可以添加文件处理程序或旋转文件处理程序,以将日志发送到本地文件: Http://docs.python.org/2/library/logging.handlers.html

我发现 Syslog 模块使得获得您所描述的基本日志记录行为变得非常容易:

import syslog
syslog.syslog("This is a test message")
syslog.syslog(syslog.LOG_INFO, "Test message at INFO priority")

你还可以做其他的事情,但即使只是前两行,也会得到你想要的东西。

下面是为3.2及更高版本推荐的 yaml dictConfig 方法。

记录 cfg.yml:

version: 1
disable_existing_loggers: true


formatters:
default:
format: "[%(process)d] %(name)s(%(funcName)s:%(lineno)s) - %(levelname)s: %(message)s"


handlers:
syslog:
class: logging.handlers.SysLogHandler
level: DEBUG
formatter: default
address: /dev/log
facility: local0


rotating_file:
class: logging.handlers.RotatingFileHandler
level: DEBUG
formatter: default
filename: rotating.log
maxBytes: 10485760 # 10MB
backupCount: 20
encoding: utf8


root:
level: DEBUG
handlers: [syslog, rotating_file]
propogate: yes


loggers:
main:
level: DEBUG
handlers: [syslog, rotating_file]
propogate: yes

使用以下方法加载配置:

log_config = yaml.safe_load(open('cfg.yml'))
logging.config.dictConfig(log_config)

配置了 syslog 和直接文件。请注意,/dev/log是特定于操作系统的。

我把它固定在我的笔记本上。 rsyslog 服务没有监听套接字服务。

我在 /etc/rsyslog.conf文件中配置了下面这行代码,并解决了这个问题:

$SystemLogSocketName /dev/log

我使用 JSON 日志记录,并希望在 UDP 端口514中使用 SysLogHandler。最终使 JSON 处理程序配置正常工作。在处理器部分,我有:

{
"syslog": {
"class": "logging.handlers.SysLogHandler",
"address": ["127.0.0.1", 514],
"facility": "local6",
"formatter": "syslog_fmt"
}

在别的地方没找到这个。

[编辑] 为了更清楚地了解这里发生了什么: 这仅用于 python 代码,并使用 python 内置的日志模块。该模块允许配置日志消息的格式和目标。配置日志格式和目标的一种方法是使用用于配置日志的 JSON 文件。

上面的示例允许我向 syslog 守护进程发送日志消息。

下面是这样一个文件的完整示例。

{
"version": 1,
"disable_existing_loggers": "False",
"formatters": {
"verbose": {
"format": "%(asctime)s:%(levelname)s:%(process)d:%(filename)s:%(funcName)s:L%(lineno)d:%(message)s"
},
"syslog": {
"format": "%(levelname)s:%(process)d:%(filename)s:%(funcName)s:L%(lineno)d:%(message)s"
}
},
"handlers": {
"console": {
"class":"logging.StreamHandler",
"formatter": "standard"
},
"syslog": {
"class": "logging.handlers.SysLogHandler",
"address": ["127.0.0.1", 514],
"facility": "local6",
"formatter": "syslog_fmt"
}
},
"loggers": {
"": {
"handlers": ["console","syslog"],
"level": "DEBUG",
"propagate": "True"
}
}
}

上面的示例将 python 日志消息发送到 syslog 和控制台。目的地的消息格式是不同的(syslog 已经在每条消息的前面加上了时间戳)。对于 syslog 目标,日志使用工具 LOCAL6。