保存数据库服务器的日志输出,而非通过 /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 处理文件轮换。为此,请将配置参数 log_destination
设置为 syslog
(仅记录到 syslog)在 postgresql.conf
中。然后,无论何时您希望强制 syslog 守护进程开始写入新日志文件,都可以向其发送 SIGHUP
信号。如果您希望自动执行日志轮换,logrotate 程序可以配置为与 syslog 中的日志文件配合使用。
然而,在大多数系统中,syslog 不是非常可靠,特别是包含大型日志消息时;当您最需要消息时,它可能会截断消息或遗落消息。此外,在 Linux 上,syslog 会将每条消息刷新到磁盘,这会导致性能很差。(您可以在 syslog 配置文件中的文件名开头使用 “-
” 来禁用同步。)
请注意,以上所描述的所有解决方案都负责按照配置的时间间隔启动新的日志文件,但它们不负责删除旧的、不再有用的日志文件。您可能需要设置一个批处理作业来定期删除旧的日志文件。另一种做法是对轮换程序进行配置,以便循环覆盖旧的日志文件。
pgBadger 是一个执行复杂日志文件分析的外部项目。当重要的消息出现在日志文件中时,check_postgres 会提供 Nagios 提醒,它也会检测很多其他异常情况。