Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 多个处理器记录到同一个文件_Python_Django_Logging_Uwsgi - Fatal编程技术网

Python 多个处理器记录到同一个文件

Python 多个处理器记录到同一个文件,python,django,logging,uwsgi,Python,Django,Logging,Uwsgi,我的nginx+uwsgi+django站点出现了问题。 我知道它对django+uwsgi没有什么特别的,应该是日志模块本身的东西 在我的站点中,我使用RotatingFileHandler记录特殊条目,但是,当uwsgi使用多个工作处理器运行时,今天我发现, 多个日志文件正在同时更改。例如,以下是文件片段: [root@speed logs]# ls -lth total 18M -rw-rw-rw- 1 root root 2.1M Sep 14 19:44 backend.log.7

我的nginx+uwsgi+django站点出现了问题。 我知道它对django+uwsgi没有什么特别的,应该是日志模块本身的东西

在我的站点中,我使用RotatingFileHandler记录特殊条目,但是,当uwsgi使用多个工作处理器运行时,今天我发现, 多个日志文件正在同时更改。例如,以下是文件片段:

[root@speed logs]# ls -lth
total 18M
-rw-rw-rw- 1 root root  2.1M Sep 14 19:44 backend.log.7
-rw-rw-rw- 1 root root  1.3M Sep 14 19:43 backend.log.6
-rw-rw-rw- 1 root root  738K Sep 14 19:43 backend.log.3
-rw-rw-rw- 1 root root  554K Sep 14 19:43 backend.log.1
-rw-rw-rw- 1 root root 1013K Sep 14 19:42 backend.log.4
-rw-rw-rw- 1 root root  837K Sep 14 19:41 backend.log.5
-rw-rw-rw- 1 root root  650K Sep 14 19:40 backend.log.2
-rw-rw-rw- 1 root root  656K Sep 14 19:40 backend.log
-rw-r--r-- 1 root root   10M Sep 13 10:11 backend.log.8
-rw-r--r-- 1 root root     0 Aug 21 15:53 general.log
[root@speed-app logs]#
实际上,我将rotate file设置为10M perfile,最多10个文件

我在谷歌上搜索了很多,很多人都找到了这个,似乎日志模块本身不能支持这个

我发现有人提到ConcurrentLogHandler()。 以前有人用过这个人吗?我知道这是基于文件锁的,我不知道这家伙的表现是否很好

或者有谁有更好的主意将多个uwsig实例记录到同一个文件中

谢谢。
Wesley

只是为了说明一下,这里有一个完整的解决方案示例,它使用python StreamHandler、uWSGI“daemonized file logging”和
logrotate
守护进程以循环方式登录到文件

正如您将看到的,uWSGI日志记录从您的应用程序捕获stdout/stderr,并将其重定向到stdout/stderr(默认情况下)或定义的其他记录器/处理程序

设置Django/uWSGI 您的Django
settings.py

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'default': {
            'format': '%(asctime)s - %(process)s - %(levelname)s - %(name)s : %(message)s',
        },
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
        },
    },
    'root': {
        'handlers': ['console'],
        'level': 'DEBUG',
    },
}
在代码中的某个地方

log = logging.getLogger(__name__)
log.info("test log!")
使用一些日志参数运行uWSGI

$ uwsgi --http :9090 --chdir=`pwd -P` --wsgi-file=wsgi.py \
    --daemonize=test.log \  # daemonize AND set log file
    --log-maxsize=10000  \  # a 10k file rotate
    --workers=4             # start 4 workers
输出 test.log的摘录

*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 79755)
spawned uWSGI worker 1 (pid: 79813, cores: 1)
spawned uWSGI worker 2 (pid: 79814, cores: 1)
spawned uWSGI worker 3 (pid: 79815, cores: 1)
spawned uWSGI worker 4 (pid: 79816, cores: 1)
spawned uWSGI http 1 (pid: 79817)
2015-10-12 07:55:48,458 - 79816 - INFO - testapp.views : test log!
2015-10-12 07:55:51,440 - 79813 - INFO - testapp.views : test log!
2015-10-12 07:55:51,965 - 79814 - INFO - testapp.views : test log!
2015-10-12 07:55:52,810 - 79815 - INFO - testapp.views : test log!
在同一目录中,一段时间后:

-rw-r-----   1 big  staff   1.0K Oct 12 09:56 test.log
-rw-r-----   1 big  staff    11K Oct 12 09:55 test.log.1444636554
对数旋转 或者,要自行处理旋转文件,请省略
--log maxsize
参数,并使用
logrotate
配置文件(
/etc/logrotate.d/uwsgi test app
):


请注意,上述值仅为示例,您可能不希望旋转大小为10k。有关logrotate格式的更多信息,请参阅。

如果您使用python的logrotation(当多个gunicorn进程指向同一个日志文件时),则应确保在旋转期间仅编辑主日志文件,而不重命名、移动等。为此,请复制主日志文件,然后将其清除

滚动方法的代码段(在logging.handlers.RotatingFileHandler的代码中编辑)

然后,您可以按如下方式创建记录器:

logger = logging.getLogger(logfile_name)
logfile = '{}/{}.log'.format(logfile_folder, logfile_name)
handler = RotatingFileHandler(
    logfile, maxBytes=maxBytes, backupCount=10
)
formatter = logging.Formatter(format, "%Y-%m-%d_%H:%M:%S")
formatter.converter = time.gmtime
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logger.isEnabledFor = lambda level: True
logger.propagate = 0

logger.warning("This is a log")

我的报价使用本地主机上的
日志服务器
并发送每个日志请求。这与sysloghandler的工作方式相同,嗯?Syslog是我最常用的;即使不使用“高级”服务器(例如rsyslog),您也可以。还有一种推荐的方法,其中顺便使用了队列(|),解释了它们的实现并给出了示例。您好,感谢您的详细回复,但您是否尝试过当uwsgi工作线程超过1个时?我已经验证了uwsgi的工作原理,4个进程都很好地(轮流)记录到同一个文件中,一旦达到大小,该文件就会旋转。该示例已更新,以显示“你救了我的命”的新输出。对您的方法进行一点更新。自py3.3以来,有一个rotator属性供您覆盖该代码段。
def doRollover(self):
    self.stream.close()
    if self.backupCount > 0:
        for i in range(self.backupCount - 1, 0, -1):
            sfn = "%s.%d" % (self.baseFilename, i)
            dfn = "%s.%d" % (self.baseFilename, i + 1)
            if os.path.exists(sfn):
                if os.path.exists(dfn):
                    os.remove(dfn)
                os.rename(sfn, dfn)
        dfn = self.baseFilename + ".1"
        if os.path.exists(dfn):
            os.remove(dfn)
        # os.rename(self.baseFilename, dfn) # Intead of this
        # Do this
        shutil.copyfile(self.baseFilename, dfn)
        open(self.baseFilename, 'w').close()
    if self.encoding:
        self.stream = codecs.open(self.baseFilename, "w", self.encoding)
    else:
        self.stream = open(self.baseFilename, "w")
logger = logging.getLogger(logfile_name)
logfile = '{}/{}.log'.format(logfile_folder, logfile_name)
handler = RotatingFileHandler(
    logfile, maxBytes=maxBytes, backupCount=10
)
formatter = logging.Formatter(format, "%Y-%m-%d_%H:%M:%S")
formatter.converter = time.gmtime
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logger.isEnabledFor = lambda level: True
logger.propagate = 0

logger.warning("This is a log")