反斜杠字符和 rsyslog 写入 postgres 时出现问题

反斜杠字符和 rsyslog 写入 postgres 时出现问题

我已将 rsyslog 4.6.4 配置为将邮件日志写入 PostgreSQL 数据库。一切正常,直到日志消息包含反斜杠,如下例所示:

6月12日 11:37:46 dc5 postfix/smtp[26475]: Vk0nYDKdH3sI: to=<[电子邮件保护]>,relay=----.---[---.---.---.---]:25,delay=1.5,delays=0.77/0.07/0.3/0.35,dsn=4.3.0,status=deferred(主机 ----.---[---.---.---.---] 说:451 4.3.0 写入文件 d:\pmta\spool\B\00000414 时出错,status = ERROR_DISK_FULL 在“DATA”中(回复 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: 至=<[电子邮件保护]>,中继 = ----.---[---.---.---.---]:25,延迟 = 1.5,延迟 = 0.77/0.07/0.3/0.35,dsn = 4.3.0,状态 = 延迟(主机 ----.---[199.85.216.241] 说:451 4.3.0 写入文件 d:pmtaspoolB 时出错

文件名中的 、 和被\pPostgreSQL\s解释为文字、和后跟一个 NULL 字符,从而提前终止字符串。此行为可以通过以下方式轻松确认:\B\0psB

dc=# SELECT 'd:\pmta\spool\B\00000414';
   ?column?   
--------------
 d:pmtaspoolB
(1 row)

dc=# 

有办法纠正这个问题吗?有没有我在 rsyslog 文档中找不到的方法可以转换\\\

答案1

首先,你应该真的在传递任意字符串时使用参数化查询和准备好的语句。
(这可能不是你的错——rsyslog 几乎肯定要为这种可怕的事情负责)。

如果你不能切换到更好的查询结构,Postgresencode函数可能可以帮助你(请参阅此处的文档)——指定一个编码escape,Postgres 将方便地将您传递给它的字符串中的所有反斜杠加倍。


请注意,如果你觉得自己特别迂腐,你可以使能够standard_conforming_strings,这使得 Postgres 将\字符串中的字符视为文字反斜杠,而不是将其视为转义字符的历史 (unix-y) 行为。
这种变化是否可行取决于很多因素……

相关内容