uWSGI+rsyslog 实现 rotating logging
文章目录
- 2020-01-27 更新 增加相关阅读和 Flask+uWSGI Logging rotate:重要补充。
uWSGI 可以使用 --logto / --logto2 / --daemonize
这几个参数来指定把 log 写入普通文件。但普通文件管理起来比较麻烦,我们可以利用 Ubuntu/CentOS 中自带的 Rsyslog 来实现日志管理。本文以 Ubuntu 16.04 为例。
uWSGI 的外部 logging 支持
让我们先来看看 uWSGI 内置了哪些 logging 系统支持:
1% uwsgi --logger-list
2
3*** uWSGI loaded loggers ***
4python
5syslog
6rsyslog
7socket
8redislog
9mongodblog
10file
11fd
12stdio
看来 syslog 已经在内置支持中了。不过要注意的是,上面列表中的 rsyslog 指的是 Remote Syslog ,如果你的 syslog 服务器在远程,则使用这个值,否则应该使用 syslog 。
使用外部 logging 系统
uWSGI 有两个参数来设定使用 外部的 logging 系统。req-logger
包含 uWSGI 的请求 log,而 logger
包含标准错误。
下面的设置将 req-logger
和 logger
分别命名,并使用了 local5 这个 facility 。local5 是可选的,也可以仅包含名称。
1[uwsgi]
2req-logger = syslog:game-proxy-req,local5
3logger = syslog:game-proxy,local5
设置 syslog
创建文件夹 /var/log/uwsgi
用来保存 uwsgi 的 log,并设置正确的权限:
1sudo chown syslog:adm /var/log/uwsgi
加入一个文件: /etc/rsyslog.d/80-game.conf
,内容如下:
1# local5.* /var/log/uwsgi/game-all.log
2:programname,isequal,"game-proxy" /var/log/uwsgi/game-proxy.log
3:programname,isequal,"game-proxy-req" /var/log/uwsgi/game-proxy-req.log
programname
就代表每条 log 的静态名称,在这里 Message Properties 。isequal
代表完全相等判断,在 Compare-Operations 这里可以找到所有可用的比较类型。
上面的配置根据 uWSGI 中配置的名称,将 log 分离到不同的文件。第一行 local5.*
则将所有使用 local5 的 log 全部置入 game-all.log
,该配置并没有启用。
设置完成后重启 rsyslog 服务:
1sudo service rsyslog restart
设置 logrotate
logrotate Ubuntu 自带的压缩、分隔 log 文件的工具,它被 crontab 调用。有了 logrotate ,我们就不必自己设计压缩和分割方案。
主 logrotate 配置文件在 /etc/logrotate.conf
,文件夹 /etc/logrotate.d/
中的所有配置文件也会被载入。我们只需要在该文件夹中增加一个文件就可以实现对 /var/log/uwsgi
中 log 文件的压缩。下面是 /etc/logrotate.d/game
文件的内容:
1/var/log/uwsgi/game-*.log {
2 create 0664 app app
3 daily
4 rotate 60
5 compress
6 delaycompress
7 missingok
8 notifempty
9 dateext
10 dateyesterday
11}
- create 分割后创建新文件,可以指定文件权限,owner 和 group 。
- daily 每日分割。
- rotate 60 保留60天的日志。
- compress 压缩日志。
- delaycompress 延迟压缩,在下一个日志分割的时候压缩上一个日志。这样同时有两个日志没有压缩:昨天的和今天的。这样可以方便查询昨天的内容。
- missingok 没有日志文件的时候不报错。
- notifempty 空日志不处理。
- dateext 使用日期作为分割日志后缀名称。若不设置则使用序号。
- dateyesterday 当设置了 dateext 的时候有效。在分割日志后面加上昨天的日期,这样文件后面的日期和文件中记录的时间戳时间是一致的。
更多详细的设置,可以看 logrotate 的 man page 。
logrotate 是被 crontab 自动调用的,详细的配置可以看文件: /etc/cron.daily/logrotate
。
如果等不及 crontab 执行,可以自行使用下面的命令测试:
1logrotate -df /etc/logrotate.d/game
使用 python 的 logging 模块
Python 自带 logging 模块。我们也可以禁用 uWSGI 中的设置,改为使用 Python 语言的 logging 模块向 rsyslog 记录日志。之前我写过一篇这样的文章:rsyslog/Python/LogAnalyzer 记录和查看日志 。
查看日志可以使用 LogAnalyzer 这个 PHP 写成的前端,用法在 rsyslog/Python/LogAnalyzer 记录和查看日志 一文中也有提到。
单独使用 logrotate
当然,我们也可以不使用 Rsyslog ,直接对 --logto / --logto2 / --daemonize
这几个参数生成的 log 文件执行 logrotate。
但要注意一个问题,当 logrotate 生效后,log 依然写入旧的文件!
举例说明:
- 原始的 log 文件名称为
uwsgi.log
; - 执行
logrotate -vf /etc/logrotate.d/game
,rotate 成功,文件名被修改为uwsgi.log-20171012
,并创建了新文件uwsgi.log
; - 此时发现新的 log 依然被写入
uwsgi.log-20171012
而非uwsgi.log
!
这是因为在 linux 系统下,一个进程打开文件时使用的是文件系统的 inode 编号而非文件名。移动或者重命名一个文件,并不会修改它的 inode 编号。因此需要在进行 rotate 之后,通知 uwsgi 重新打开 log 文件。
或者,可以将 create
创建方式修改为 copytruncate
创建方式,后者的特点是复制一份现有的 log 为新文件,然后清空旧文件。这样就不需要通知 uwsgi 重新打开 log 文件了。
copytruncate
的缺点就是,复制 log 文件和清空 log 文件之间有一段时间(若 log 文件较大就更明显),这段时间中的 log 文件可能丢失。
copytruncate
还有一个关于权限的问题。 create
可提供文件权限,owner/group 信息,而 copytruncate
则是直接复制原始文件的权限。在使用 copytruncate
的时候,可以使用 su
来设置文件权限。上面的配置文件可以改成这样:
1/var/log/uwsgi/game-*.log {
2 su app app
3 copytruncate
4 daily
5 rotate 60
6 compress
7 delaycompress
8 missingok
9 notifempty
10 dateext
11 dateyesterday
12}
如果仍然希望使用 create
参数,那么可以参考 Flask+uWSGI 的 Logging 支持 中的“uWSGI 的 Logging 配置“一节。
参考
相关阅读
- 部署Flask + uWSGI + Nginx
- Flask+uWSGI 的 Logging 支持
- Flask+uWSGI Logging rotate:重要补充
- pyzog:uWSGI logging rotate 的终极方案
- 文章ID:2631
- 原文作者:zrong
- 原文链接:https://blog.zengrong.net/post/uwsgi-rsyslog-rotating-logging/
- 版权声明:本作品采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可,非商业转载请注明出处(原文作者,原文链接),商业转载请联系作者获得授权。