syslog-ng не очищает канал от внешней программы

Я написал скрипт Python, который принимает записи журнала от syslog-ng и записывает их в MongoDB (я не мог сделать это с драйвером afmongodb, потому что мне нужно выполнить некоторую специальную обработку).

Вот как это выглядит в syslog-ng.conf:

destination d_mongodb_events {
  program("/home/test/syslog_piper.py"
    template("$UNIXTIME|$PRIORITY|$FACILITY|$SOURCEIP|$SEQNUM|$PID|$PROGRAM|$MSGONLY\n")
    flags(no_multi_line)
    flush_lines(1)
    flush_timeout(1000)
  );
};

И это скрипт: (без логики)

import sys
try:
    lines = sys.stdin.readlines()
    for line in lines:
        # process `line` and save to DB

except Exception, e:
    f = open('/tmp/error.txt','ab')
    f.write(e)
    f.close()
    exit(0)

Скрипт работает - то есть, если я запускаю его из командной строки, он ждет ввода и вставляет строки в БД, как только я нажимаю Ctrl+D - и выходит.

С syslog-ng это отличается. Записи передаются в скрипт, но только после того, как я остановил демон syslog-ng. Кроме того, пока запущен syslog-ng, я вижу, что мой скрипт тоже работает (в списке процессов). Я пробовал настройку flush_lines() а также flush_timeout() (см. конфигурацию выше), но я не могу заставить syslog-ng сбрасывать вывод.

Я предполагаю, что что-то не так с тем, как я обращаюсь с конвейерами, но я не могу понять это. Кто-нибудь может определить проблему?

ОБНОВЛЕНИЕ: если я отправляю 1000 сообщений, некоторые из них проталкиваются, поэтому я предполагаю, что происходит некоторая буферизация. Кто-нибудь знает, какую настройку настроить?

РЕШЕНИЕ: похоже, что Python буферизует большую часть своего ввода / вывода. Это из справочных страниц:

 -u       Force  stdin,  stdout  and  stderr to be totally unbuffered.  On
          systems where it matters, also put stdin, stdout and  stderr  in
          binary  mode.   Note  that there is internal buffering in xread-
          lines(), readlines() and file-object  iterators  ("for  line  in
          sys.stdin")  which  is  not  influenced by this option.  To work
          around this, you will want to use "sys.stdin.readline()"  inside
          a "while 1:" loop.

Так что в основном мне пришлось изменить программу, чтобы использовать sys.stdin.readline(), Огромное спасибо Янне.

1 ответ

Решение

Я не подключал никакие скрипты Python к syslog-ng, но с помощью скриптов Perl я должен отключить буферизацию вывода, прежде чем они будут работать в режиме реального времени. В Perl говорят, что это $|=1,

Я не очень-то разбираюсь в Python, но, думаю, я запускаю ваш скрипт на Python с -u или настройка переменной PYTHONUNBUFFERED может помочь.

Другие вопросы по тегам