简体   繁体   English

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM