Обработка logrotate в открытом () - PullRequest
2 голосов
/ 10 апреля 2020

Я использую следующую функцию, чтобы следовать и обрабатывать файл журнала построчно:

def tail(f):
    f.seek(0,2)
    while True:
        line = f.readline()
        if not line:
            time.sleep(0.1)
            continue
        yield line

with open("/var/log/some.log") as f:
    for line in tail(f):
    ...

Когда logrotate поворачивает файл, эта функция застревает в последней строке. Я полагаю, что logrotate перемещает файл и создает новый, в результате чего программа все еще ожидает строки из старого.

Какой хороший способ справиться с этим - повторно открыть файл при повороте?

1 Ответ

2 голосов
/ 10 апреля 2020

Стандартный обычный способ - сказать logrotate отправить сигнал HUP службе / программе, которая обрабатывает журналы.

В конфигурации logrotate это делается с помощью постротационного скрипта:

   postrotate
       /usr/bin/killall -HUP your_process
   endscript

Тогда в вашей программе python вам придется обрабатывать сигнал HUP. У вас есть пример в сигнале python do c. Вы захотите обработать signal.SIGHUP


Другой, менее стандартный способ сделать это - сравнить номер инода с (возможно) новым номером инода. Если эти цифры отличаются, то вы знаете, что файл изменился, и вам нужно открыть его снова.

Я пробовал что-то подобное, и это, похоже, сработало:

import os
import time

logname = "logfile"
logfile = open(logname, "r")

def tail(f):
    f.seek(0,2)
    inode = os.fstat(f.fileno()).st_ino

    while True:
        line = f.readline()
        if not line:
            time.sleep(0.1)
            if os.stat(logname).st_ino != inode:
                f.close()
                f = open(logname, 'r')
                inode = os.fstat(f.fileno()).st_ino
            continue
        yield line

for line in tail(logfile):
    ...
...