用supervisor管理运行的python程序,将stdout配置到指定log文件,supervisor配置节点示例如下:
[program:web] command = /var/www/env/bin/python run.py --port=808%(process_num)01d --address=127.0.0.1 autostart = true startsecs = 5 user = root redirect_stderr = true directory = /var/www/ numprocs=4 process_name=%(program_name)s_%(process_num)02d stdout_logfile = /var/log/supervisor/www.log
结果发现supervisor输出的日志文件 www.log 跟程序输出的不一致,少了很多日志输出。
比如同一秒并发了5个请求,www.log却只有一行日志,这样我配置好的fail2ban通过www.log日志文件的匹配规则来定位,当然就不能正确地计算出访问数量。
有想到是stdout的buffer导致的,在网上google后找到了答案:
If you are also using Supervisor to monitor and heal your long running Python projects and observed that output of your program is not being logged to stdout_logfile, it is because Python print statement does not automatically flush output to STDOUT.
One solution is using sys.stdout.flush() frequently to flush the output or if you are using Python 3.3, print(msg, flush=True) is another solution. However, a better solution is to run python with -u parameter (unbuffered mode).
较好的解决办法是修改supervisor配置,在启动python进程的cmd中添加-u参数,如:
[program:web] command = /var/www/env/bin/python run.py -u --port=808%(process_num)01d --address=127.0.0.1
参考:
https://stackoverflow.com/questions/15453234/why-does-stdout-not-flush-when-connecting-to-a-process-that-is-run-with-supervis
https://ahmet.im/blog/redirecting-output-of-python-programs-supervisor/