Python 3.6.8: бесконечный цикл разветвленного потока не приводит к регистрации stderr в systemd из-за буферизации по умолчанию

#python #multithreading #systemd #stderr #socketserver

#питон #многопоточность #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», в файле 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
 

Ответ №1:

Я нашел решение. Оставляем это для дальнейшего использования.

На самом деле это была вообще не проблема systemd, а скорее проблема с буферизацией.

Отключение буферизации Python по умолчанию (для версий <3.7), запустив «python -u» или используя переменную среды PYTHONUNBUFFERED, приводит к правильному протоколированию всех выходных данных.