Python 3.6.8:由于默认缓冲,无限循环分叉线程导致systemd上没有stderr日志记录



我的python守护程序是通过systemd运行的,stderr记录在一个文件上。

systemd服务文件的简化版本如下:

[Unit]
Description=Test
[Service]
ExecStart=/path/to/test.py
StandardError=file:/path/to/error.log
[Install]
WantedBy=multi-user.target

python守护进程实例化一个线程TCP服务器,并在其上永远运行serve_forever。问题是线程启动未记录在error.log文件中之后发生的任何错误。记录之前发生的任何错误。

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

如果我取消注释";barfoo";,a";名称未定义";记录在error.log文件中。

如果我取消注释";foobar";,没有任何记录。

此外,由于TCP服务器线程仍在运行,systemd守护进程显示为正在运行,因此我甚至无法从中检测到错误。

如果我从命令行运行守护程序,两个错误都会正确地记录在stderr上(如果我重定向文件中的stderr,则会重定向(。在systemd脚本中尝试相同的重定向,而不是StandardError指令,其效果与后者相同。

编辑:我用一个通用的无限循环线程测试了同样的东西,以获得同样的效果:

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

我找到了解决方案。留作参考。

实际上,这根本不是一个系统问题,而是一个缓冲问题。

禁用默认Python(对于版本<3.7(缓冲;python-u";或者使用PYTHONNBUFFERED环境变量使得所有输出都被正确地记录。

最新更新