将数据库服务器的日志输出保存到某处是一个好主意,而不是简单地通过 /dev/null
丢弃。日志输出在诊断问题时非常有价值。
服务器日志可能包含敏感信息,无论其如何存储、存储在哪里或路由到何处,都需要对其进行保护。例如,某些 DDL 语句可能包含明文密码或其他认证详细信息。记录 ERROR
级别的语句可能会显示应用程序的 SQL 源代码,并且可能还包含部分数据行。记录数据、事件和相关信息是此功能的目标,因此这不是泄露或错误。请确保服务器日志仅对授权人员可见。
日志输出往往非常庞大(尤其是在较高的调试级别时),因此您不会想无限期地保存它。您需要轮换日志文件,以便在合理的时间段后启动新的日志文件并删除旧的日志文件。
如果您只是将 postgres
的 stderr 重定向到一个文件,您将获得日志输出,但截断日志文件的唯一方法是停止并重启服务器。如果您在开发环境中使用 PostgreSQL,这可能可以接受,但很少有生产服务器会认为这种行为可以接受。
更好的方法是将服务器的 stderr 输出发送到某种日志轮换程序。有一个内置的日志轮换功能,您可以通过在 postgresql.conf
中将配置参数 logging_collector
设置为 true
来使用它。该程序的控制参数在 第 19.8.1 节 中描述。您还可以使用此方法以机器可读的CSV(逗号分隔值) 格式捕获日志数据。
或者,如果您已经在使用某个外部日志轮换程序与其他服务器软件配合使用,您可能更喜欢使用它。例如,Apache 发行版中包含的 rotatelogs 工具可以与 PostgreSQL 一起使用。一种方法是将服务器的 stderr 输出通过管道传递给所需的程序。如果您使用 pg_ctl
启动服务器,那么 stderr 已经被重定向到 stdout,所以您只需要一个管道命令,例如
pg_ctl start | rotatelogs /var/log/pgsql_log 86400
您可以通过设置 logrotate 来收集 PostgreSQL 内置日志收集器生成的日志文件,从而结合这些方法。在这种情况下,日志收集器定义日志文件的名称和位置,而 logrotate 定期归档这些文件。在启动日志轮换时,logrotate 必须确保应用程序将进一步的输出发送到新文件。这通常是通过一个 postrotate
脚本来完成的,该脚本向应用程序发送一个 SIGHUP
信号,然后应用程序会重新打开日志文件。在 PostgreSQL 中,您可以改用带 logrotate
选项的 pg_ctl
。当服务器收到此命令时,服务器会根据日志配置(参见 第 19.8.1 节)切换到新日志文件或重新打开现有日志文件。
在使用静态日志文件名时,如果达到最大打开文件数限制或发生文件表溢出,服务器可能无法重新打开日志文件。在这种情况下,日志消息会发送到旧日志文件,直到成功进行日志轮换。如果 logrotate 配置为压缩日志文件并删除它,服务器可能会丢失在此期间记录的消息。为了避免此问题,您可以配置日志收集器动态分配日志文件名,并使用 prerotate
脚本来忽略已打开的日志文件。
另一种生产级别的日志输出管理方法是将其发送到 syslog,然后让 syslog 处理文件轮换。要做到这一点,请在 postgresql.conf
中将配置参数 log_destination
设置为 syslog
(仅记录到 syslog)。然后,您可以随时向 syslog 守护进程发送一个 SIGHUP
信号,以强制它开始写入新的日志文件。如果您想自动化日志轮换,可以配置 logrotate 程序与 syslog 的日志文件一起工作。
然而,在许多系统上,syslog 并不可靠,尤其是处理大型日志消息时;它可能会在您最需要它们的时候截断或丢弃消息。此外,在 Linux 上,syslog 会将每条消息刷新到磁盘,导致性能不佳。(您可以在 syslog 配置文件中的文件名开头使用“-
”来禁用同步。)
请注意,上面描述的所有解决方案都负责在可配置的间隔开始新的日志文件,但它们不处理旧的、不再有用的日志文件的删除。您可能需要设置一个批处理作业来定期删除旧日志文件。另一种可能性是配置轮换程序,以便旧日志文件被循环覆盖。
pgBadger 是一个进行复杂日志文件分析的外部项目。check_postgres 在日志文件中出现重要消息时提供 Nagios 警报,并检测许多其他异常情况。
如果您在文档中看到任何不正确、与您对特定功能的实际体验不符或需要进一步澄清的内容,请使用此表格报告文档问题。