我有rsyslog 4.6.4configuration写邮件日志到PostgreSQL数据库。 它一切正常,直到日志消息包含一个反斜杠,如下例所示:
Jun 12 11:37:46 dc5 postfix / smtp [26475]:Vk0nYDKdH3sI:to = <—–@—-.—>,relay = —-.— [—延迟= 1.5,延迟= 0.77 / 0.07 / 0.3 / 0.35,dsn = 4.3.0,status = deferred(host —-.— [ —。—。— .—]说:451 4.3.0写入文件d:\ pmta \ spool \ B \ 00000414时出错,“DATA”中的status = ERROR_DISK_FULL(回复DATA命令))
以上是写入/var/log/mail.log的日志条目。 它是正确的。 问题在于,发送到以下SQL配方时,文件名中的反斜杠字符将被解释为转义字符:
$template dcdb, "SELECT rsyslog_insert(('%timereported:::date-rfc3339%'::TIMESTAMPTZ)::TIMESTAMP,'%msg:::escape-cc%'::TEXT,'%syslogtag%'::VARCHAR)",STDSQL :syslogtag, startswith, "postfix" :ompgsql:/var/run/postgresql,dc,root,;dcdb
因此, rsyslog_insert()存储过程对于msg获取以下值:
Vk0nYDKdH3sI:to = <—–@—-.—>,relay = —-.— [—. —。。.–]:25 ,delay = 1.5,delay = 0.77 / 0.07 / 0.3 / 0.35,dsn = 4.3.0,status = deferred(主机—-.— [199.85.216.241]表示:451 4.3.0写入文件d时出错:pmtaspoolB
文件名中的\p , \s , \B和\0被PostgreSQL解释为文字p , s和B后跟NULL字符,从而提前终止string。 这种行为可以很容易地确认:
dc=# SELECT 'd:\pmta\spool\B\00000414'; ?column? -------------- d:pmtaspoolB (1 row) dc=#
有没有办法纠正这个问题? 有没有一种方法,我没有在rsyslog文档中find变成\\ ?
首先,在传递任意string时,您应该真正使用参数化的查询和准备语句。
(这可能不是你的错 – rsyslog几乎肯定是造成这个恐怖的原因)。
如果你不能切换到一个更好的查询结构Postgres encodefunction可能可以帮助你( 见这里的文档 ) – 指定一个编码escape和Postgres将方便地加倍你所有的反斜杠你传递给它。
请注意,如果您感觉特别迂腐,则可以启用standard_conforming_strings ,这使得Postgres将string中的\字符视为文字反斜杠,而不是将其作为转义字符处理的历史(unix-y)行为。
在你的环境中这种变化是否可行取决于很多因素