#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, приводит к правильному протоколированию всех выходных данных.