[英]Python 3.6.8: infinite looping forked thread causes no stderr logging on systemd due to default buffering
My python daemon is run through systemd, with stderr logging on a file.我的 python 守护程序通过 systemd 运行,stderr 记录在文件上。
A simplified version of the systemd service file is this: systemd 服务文件的简化版本如下:
[Unit]
Description=Test
[Service]
ExecStart=/path/to/test.py
StandardError=file:/path/to/error.log
[Install]
WantedBy=multi-user.target
The python daemon instantiates a threaded TCP server and runs serve_forever on it. python 守护进程实例化一个线程化的 TCP 服务器并在其上运行 serve_forever。 The problem is any error happening after the thread start is not logged on the error.log file.
问题是线程启动后发生的任何错误都没有记录在 error.log 文件中。 Any error happening before is logged.
记录之前发生的任何错误。
A simplified version of the python daemon is this: python 守护程序的简化版本是这样的:
import threading, socketserver
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
class TCPHandler(socketserver.BaseRequestHandler):
def handle(self):
pass
#barfoo
TCPServer = ThreadedTCPServer(("127.0.0.1", 12345), TCPHandler)
TCPThread = threading.Thread(target=TCPServer.serve_forever)
TCPThread.start()
#foobar
If I uncomment "barfoo", a "name not defined" is logged in the error.log file.如果我取消注释“barfoo”,则会在 error.log 文件中记录“名称未定义”。
If I uncomment "foobar", nothing is logged.如果我取消注释“foobar”,则不会记录任何内容。
Also, since the TCP server thread is still running, the systemd daemon is shown as running, so I can't even detect the error from there.此外,由于 TCP 服务器线程仍在运行,systemd 守护进程显示为正在运行,所以我什至无法从那里检测到错误。
If I run the daemon from command line, both errors are correctly logged on stderr (and redirected if I redirect stderr on a file).如果我从命令行运行守护程序,则两个错误都会正确记录在 stderr 上(如果我在文件上重定向 stderr,则会重定向)。 Trying the same redirect in the systemd script, instead of the StandardError directive, has the same effect as the latter.
在 systemd 脚本中尝试相同的重定向,而不是 StandardError 指令,与后者具有相同的效果。
EDIT: I tested the same thing with a generic infinite looping thread, for the same effect:编辑:我用一个通用的无限循环线程测试了同样的东西,效果相同:
import threading
def run():
while True:
pass
#aaaaaa # logs an error on systemd's stderr
test_thread = threading.Thread(target=run)
test_thread.start()
#foobar # doesn't log an error on systemd's stderr
I found the solution.我找到了解决方案。 Leaving this for future reference.
留下这个以备将来参考。
It was actually not a systemd problem at all, but rather a buffering problem.这实际上根本不是系统问题,而是缓冲问题。
Disabling the default Python (for versions < 3.7) buffering, by running "python -u" or using the PYTHONUNBUFFERED environment variable, causes all the output to be correctly logged.通过运行“python -u”或使用 PYTHONUNBUFFERED 环境变量禁用默认的 Python(对于版本 < 3.7)缓冲,会导致正确记录所有 output。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.