PostgreSQL 的 log_directory、log_filename 和 log_file_mode 经常被当成三个独立的配置项,但它们其实共同描述了日志采集器写入文件时的三个问题:日志放在哪里、文件叫什么,以及哪些用户可以读取。还有一个容易被忽略的前提:logging_collector 没有开启时,这三个参数都不会产生实际效果。
默认值在个人电脑上通常足够省心,但放到服务器上就未必合适。问题不只是“日志能不能写出来”,还涉及轮转、采集器发现路径、文件权限和运维人员的排障效率。
先确认日志采集器是否工作
这三个 GUC 描述的是日志采集器写入的文件,而不是所有 PostgreSQL 日志输出路径。可以先在数据库中检查当前状态:
SELECT name, setting, unit, context, sourcefile, sourceline
FROM pg_settings
WHERE name IN (
'logging_collector',
'log_directory',
'log_filename',
'log_file_mode'
)
ORDER BY name;
如果 logging_collector 是 off,PostgreSQL 可能仍会通过标准错误输出日志,由外部服务管理这些内容,但上面三个文件相关参数不会决定日志最终写到哪里。
logging_collector 通常需要重启 PostgreSQL 才能启用;其他参数的生效方式应以 pg_settings.context 为准。修改前可以查看配置来源,避免把一个由命令行、包含文件或自动化系统管理的值直接覆盖掉。
三个参数分别控制什么
log_directory:目录路径
log_directory 指定日志文件目录。使用相对路径时,它通常相对于数据库集群的数据目录;使用绝对路径则可以把日志放到专门的文件系统中。
相对路径适合简单的单机部署,例如:
log_directory = 'log'
服务器上可以考虑使用独立挂载点,例如:
log_directory = '/var/log/postgresql'
独立目录更便于设置磁盘配额、监控空间使用情况和配置外部日志采集器。代价是目录必须提前创建,并且 PostgreSQL 运行用户必须拥有写权限。日志目录放在数据目录之外时,还要确认备份、清理和安全策略是否覆盖了这条新路径。
log_filename:文件名模式
log_filename 是日志文件名模板,可以使用时间格式字段生成按时间变化的文件名。一个常见的实践是按日期和时间生成文件:
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
文件名设计需要服务于实际运维流程:
- 外部采集器通常需要稳定的目录和可预测的文件后缀。
- 文件名包含日期后,人工查找和按日期归档更直观。
- 文件名包含秒级时间戳时,可以减少同名覆盖,但也可能产生更多文件。
- 文件轮转策略应与文件名模式一起检查,避免文件数量持续增长。
不要只关注“文件名看起来是否清楚”。还需要验证 PostgreSQL 的轮转行为、操作系统的清理任务,以及日志采集器是否能识别新文件。
log_file_mode:Unix 文件权限
log_file_mode 控制采集器创建日志文件时使用的 Unix 权限模式。可以把它理解为日志文件的初始访问边界,而不是目录权限的替代品。
例如,服务器上通常希望只有 PostgreSQL 运行用户能够读取日志:
log_file_mode = 0600
如果确实需要同一组运维用户读取,可以在经过验证的 Unix 用户组和目录权限模型下使用更宽松的模式,例如:
log_file_mode = 0640
这里的风险很具体:日志可能包含 SQL 文本、用户名、客户端地址、错误详情,甚至应用误写入的敏感数据。把权限放宽到所有本机用户,往往意味着把数据库运行信息暴露给不需要它的人。
修改该参数通常只影响新创建的日志文件。已经存在的文件不会因为配置值改变而自动收紧权限,因此变更后要检查旧文件和轮转文件的权限。
一个可直接改造的配置示例
下面是一份面向 Linux 服务器的示例。假设 PostgreSQL 运行用户是 postgres,日志目录由系统管理员创建,且外部采集器会读取这个目录:
sudo install -d -o postgres -g postgres -m 0750 /var/log/postgresql
sudo -u postgres psql -d postgres <<'SQL'
ALTER SYSTEM SET logging_collector = 'on';
ALTER SYSTEM SET log_directory = '/var/log/postgresql';
ALTER SYSTEM SET log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log';
ALTER SYSTEM SET log_file_mode = '0600';
SQL
sudo systemctl restart postgresql
重启后检查配置和实际文件:
sudo -u postgres psql -d postgres -c \
"SELECT name, setting, context FROM pg_settings WHERE name IN ('logging_collector', 'log_directory', 'log_filename', 'log_file_mode') ORDER BY name;"
sudo find /var/log/postgresql -maxdepth 1 -type f -printf '%M %u %g %p\n'
请根据发行版调整服务名和 PostgreSQL 数据库名。ALTER SYSTEM 会写入 postgresql.auto.conf,适合集中记录实例级配置,但不要让它和配置管理系统同时管理同一组参数。生产环境还应补充日志轮转、磁盘空间告警和采集器权限验证。
采用前检查这几件事
一套可用的服务器配置不只是在 postgresql.conf 中填三个值,还应确认:
logging_collector已开启,并且确实完成了需要的重启。log_directory存在,路径对 PostgreSQL 运行用户可写。log_filename产生的文件能被日志轮转和采集系统发现。log_file_mode与实际排障人员的读取需求匹配,默认优先选择最小权限。- 旧日志文件的权限、磁盘占用和清理周期已经单独检查。
- 配置来源明确,不会被
postgresql.auto.conf、配置管理工具或启动参数互相覆盖。
核心原则很简单:先确认谁负责写日志,再决定目录、文件名和权限。桌面环境可以接受默认值;服务器环境则应该把这三个 GUC 放进完整的日志生命周期设计中一起评估。