2010-10-19 274 views
94

我无法摆脱Python的logging模块。我的需求非常简单:我只想将所有内容记录到系统日志中。在阅读文档后,我想出了这个简单的测试脚本:如何在Python中将日志记录配置到系统日志?

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中产生任何日志记录。怎么了?

+3

你在哪里检查你的系统日志消息? SysLogHandler()将这些消息发送到localhost中端口514的udp套接字。 – suzanshakya 2010-10-19 14:21:40

+0

你是对的。我在文档中看到'localhost-514',但没有想到应该使用/ dev/log默认情况下..叹息.. – thor 2010-10-19 18:28:47

回答

109

更改行这样的:

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') 
+9

请注意,由于[文档](http://docs.python.org/2/library/logging.handlers.html#logging.handlers.SysLogHandler)说,'/ var/run/syslog'是在OS X上正确的事情。 – offby1 2014-02-14 20:55:02

+0

Lifesaver answer +1 – chachan 2017-04-12 13:34:51

+2

我们如何在syslog中识别这些日志?像我们可以给任何应用程序名称或任何标签,如syslogtag = django? – Luv33preet 2017-06-28 14:41:32

9

是否将您的syslog.conf设置为处理facility = user?

你可以设置所用的蟒蛇记录器与设备参数的设备,这样的事情:

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

您需要指定您提供的作为值的LOG_DAEMON是什么对于'facility'参数。 – tzot 2010-10-19 20:55:05

+1

这将是'SysLogHandler.LOG_DAEMON'。 – 2011-11-02 22:12:24

11

我添加了一点额外的评论,以防万一它帮助任何人,因为我发现这个例子有用的,但需要这一点额外的信息,以使其工作。

要使用SysLogHandler登录到特定设施,您需要指定设施值。 说,例如,您已经定义:

local3.* /var/log/mylog

在系统日志,那么你要使用:

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

,你还需要对UDP的syslog监听使用localhost而不是/ dev/log。

+1

没有'需要'让系统日志侦听UDP。你的例子也可以完美的使用address ='/ dev/log'。 – thor 2012-06-28 21:14:42

+4

是的,当然,但是地址=('localhost',514),当你有日志服务器的时候,你用服务器的地址代替localhost,并且你有远程日志记录;-) – 2012-09-20 15:31:42

+3

设施= 19哪里来从?为什么不是facility =“local3” – boatcoder 2013-10-14 17:36:13

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

上面的脚本将记录到我们的定制“LOG_IDENTIFIER” ...... LOCAL0功能,您可以使用本地[0-7]本地的目的。

+1

您的评论与原始请求无关 – thor 2012-06-28 21:12:32

+2

@thor是怎么回事?这里的回复相当有效... – Cmag 2013-11-11 22:07:36

16

您应该总是使用本地主机进行日志记录,无论是通过TCP堆栈/ dev/log还是localhost。这使完全RFC兼容和有功能的系统日志守护进程能够处理系统日志。这消除了远程守护进程的功能,并提供了syslog守护进程的增强功能,例如rsyslog和syslog-ng。 SMTP也是一样的理念。只需将它交给本地SMTP软件即可。在这种情况下,使用'程序模式'不是守护进程,但它是一样的想法。让功能更强大的软件处理它。重试,排队,本地假脱机,为syslog使用TCP而不是UDP等等变得可能。您也可以按照应该的方式[从代码中分别重新配置这些守护程序]。

保存你的应用程序的编码,让其他软件完成它的工作。

+0

你提出了一个公平的观点。你能指出各种日志守护进程使用的公共地址和端口吗?有没有标准的发现机制来确定守护进程是否绑定到tcp套接字? – 2018-02-26 17:56:16

7

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') 
+0

这非常有趣,但它不适用于python 2.6.6(RHEL 6.4):Traceback(最近调用最后一次): 文件“syslog_bridge.py”,第68行,在 handlers.append(SysLogLibHandler logFacilityLocalN)) 文件“syslog_bridge.py”,第29行,在__init__中 syslog.openlog(syslog.LOG_PID,self.FACILITY [n]) TypeError:ident string [,logoption [,facility]] – 2014-04-25 13:40:54

+0

根据: https://github.com/luismartingil/scripts/commit/46c947233ca58530bd55336cdc810e9e51c84c90 – luismartingil 2014-04-27 18:15:46

12

凑合的东西从这里和其他地方在一起,这是我想出了适用于unbuntu 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") 
+1

要在centOS7上重新启动rsyslog,'sudo service rsyslog restart' – radtek 2017-04-21 18:09:46

7

我发现the syslog module使它很容易得到你所描述的基本记录行为:

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

还有其他的事情你也可以做,但即使只是前两行,你会得到你所要求的,因为我理解它。

+0

我保留记录模块,因为它允许更改记录器设置而不影响所有的语句。此外,如果您想在此时使用不同类型的日志记录,还可以更改行为 – chachan 2017-04-12 13:38:35

1

下面是yaml dictConfig方式推荐用于3.2 &以后。

在日志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) 

配置了系统日志&直接文件。请注意0​​是操作系统特定的。