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
может помочь.