Назад | Перейти на главную страницу

Проблема с символами обратной косой черты и записью rsyslog в postgres

У меня rsyslog 4.6.4 настроен для записи журналов почты в базу данных PostgreSQL. Все работает нормально, пока сообщение журнала не будет содержать обратную косую черту, как в этом примере:

12 июня, 11:37:46 dc5 postfix / smtp [26475]: Vk0nYDKdH3sI: to = <-----@----.--->, relay = ----.--- [--- . ---. --- .---]: 25, задержка = 1.5, задержки = 0.77 / 0.07 / 0.3 / 0.35, dsn = 4.3.0, статус = отложено (хост ----.--- [ ---. ---. --- .---] сказал: 451 4.3.0 Ошибка записи в файл d: \ pmta \ spool \ B \ 00000414, status = ERROR_DISK_FULL в "DATA" (в ответ на конец Команда DATA))

Выше приведена запись журнала, записанная в /var/log/mail.log. Это правильно. Проблема в том, что символы обратной косой черты в имени файла интерпретируются как escape-символы при отправке по следующему рецепту 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() хранимая процедура получает следующее значение для as 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, что приводит к раннему завершению строки. Это поведение легко подтвердить с помощью:

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

dc=# 

Есть ли способ исправить эту проблему? Есть ли способ, которым я не нахожу в документах rsyslog, чтобы включить \ в \\?

Во-первых, вам следует ДЕЙСТВИТЕЛЬНО использовать параметризованные запросы и подготовленные операторы при передаче произвольных строк.
(Вероятно, это не ваша вина - rsyslog почти наверняка виноват в этом ужасе).

Если вы не можете переключиться на лучшую структуру запроса, Postgres encode функция, вероятно, может вам помочь (см. документацию здесь) - укажите кодировку escape и Postgres удобно удвоит все ваши обратные косые черты в строке, которую вы ему передаете.


Обратите внимание: если вы чувствуете себя особенно педантично, вы можете включить standard_conforming_strings, что заставляет Postgres обрабатывать \ символ в строке как буквальная обратная косая черта, а не его историческое (unix-y) поведение, когда он рассматривается как escape-символ.
Жизнеспособность такого изменения в вашей среде зависит от множества факторов ...