我编写了一个 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)
脚本有效 - 也就是说,如果我从命令行运行它,它会等待输入并在我按下时将行插入 DB 中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()
。非常感谢 Janne。
答案1
我没有将任何 Python 脚本挂接到 syslog-ng,但对于 Perl 脚本,我必须关闭输出缓冲才能实时工作。用 Perl 的话来说,就是这样$|=1
。
我不太懂 Python,但我想运行 Python 脚本-u
或设置变量PYTHONUNBUFFERED
可能会有所帮助。