Skip to content

25.3. 日志文件维护#

最好将数据库服务器的日志输出保存在某个地方,而不是通过/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 警报,以及检测许多其他异常情况。