最好将数据库服务器的日志输出保存在某个地方,而不是通过 /dev/null
丢弃它。在诊断问题时,日志输出非常有价值。
服务器日志可能包含敏感信息,无论如何或存储在何处,或路由到的目标,都需要对其进行保护。例如,某些 DDL 语句可能包含明文密码或其他身份验证详细信息。记录在 ERROR
级别的语句可能会显示应用程序的 SQL 源代码,还可能包含一些数据行的部分内容。记录数据、事件和相关信息是此功能的预期功能,因此这不是泄漏或错误。请确保只有获得适当授权的人员才能看到服务器日志。
日志输出往往很大(尤其是在较高的调试级别),因此您不想无限期地保存它。您需要轮换日志文件,以便在合理的时间段后启动新的日志文件并删除旧的日志文件。
如果您只是将 postgres
的 stderr 定向到一个文件,您将获得日志输出,但截断日志文件的唯一方法是停止并重新启动服务器。如果您在开发环境中使用 PostgreSQL,这可能是可以接受的,但很少有生产服务器会发现此行为是可以接受的。
一种更好的方法是将服务器的 stderr 输出发送到某种类型的日志轮换程序。有一个内置的日志轮换程序,你可以通过在 postgresql.conf
中将配置参数 logging_collector
设置为 true
来使用它。此程序的控制参数在 第 20.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
。当服务器收到此命令时,服务器会根据日志记录配置切换到新日志文件或重新打开现有文件(请参阅 第 20.8.1 节)。
在使用静态日志文件名时,如果达到最大打开文件限制或发生文件表溢出,服务器可能无法重新打开日志文件。在这种情况下,日志消息将发送到旧日志文件,直到成功进行日志轮换。如果将 logrotate 配置为压缩日志文件并将其删除,服务器可能会丢失在此时间范围内记录的消息。为避免此问题,你可以将日志收集器配置为动态分配日志文件名,并使用 prerotate
脚本来忽略打开的日志文件。
管理日志输出的另一种生产级方法是将其发送到 syslog,并让 syslog 处理文件轮换。为此,请在 postgresql.conf
中将配置参数 log_destination
设置为 syslog
(仅记录到 syslog)。然后,每当你希望强制 syslog 守护进程开始写入新日志文件时,都可以向其发送 SIGHUP
信号。如果你希望自动执行日志轮换,可以将 logrotate 程序配置为与 syslog 的日志文件配合使用。
然而,在许多系统上,syslog 的可靠性不高,尤其是在处理大型日志消息时;它可能会在你最需要时截断或丢弃消息。此外,在 Linux 上,syslog 会将每条消息刷新到磁盘,从而导致性能低下。(你可以在 syslog 配置文件的开始处使用文件名称中的 “-
” 来禁用同步。)
请注意,上面描述的所有解决方案都负责在可配置的时间间隔内启动新的日志文件,但它们不处理删除不再有用的旧日志文件。你可能希望设置一个批处理作业来定期删除旧日志文件。另一种可能性是配置轮换程序,以便循环覆盖旧日志文件。
pgBadger 是一个执行复杂日志文件分析的外部项目。 check_postgres 在日志文件中出现重要消息时提供 Nagios 警报,以及检测许多其他异常情况。