
先说个结论看到connection failed这种报错第一反应不应该是跑去翻防火墙而是先把报错原文一个字一个字读清楚。标题里这个报错很有意思connection to server at 1, port 5432 failed后面还跟了一个孤零零的P。这个P大概率是复制报错时被截断了但更值得注意的是那个被引号框起来的1——PostgreSQL 客户端想要连一台名字叫1的机器而这样的机器在绝大多数环境里都不存在。很多人栽在这一步问题根本不在 pgsql 服务本身而在连接参数。这篇文章我就围绕这行典型的 PostgreSQL 连接失败报错把报错怎么拆解、排错按什么顺序、真实案例怎么复盘、平时怎么避免完整过一遍。无论你是刚装完 pgsql 还连不上还是被这种报错折腾过几次的老手应该都能从里面找到能直接用的东西。1. 报错原文拆解被引号圈住的1才是核心线索1.1 connection to server at ...这是哪一层的失败PostgreSQL 客户端的连接过程大致分四步解析主机名或 IP、建立 TCP 连接、完成 SSL/TLS 协商如果启用、发送启动报文给数据库做身份认证。connection to server at 1, port 5432 failed这一步发生在最前面的解析主机名 建立 TCP阶段。也就是说客户端可能连对方的 IP 都没摸到更没到密码对不对那一层。有个点很容易被忽略server at 1里面的1并不是什么固定参数而是客户端实际尝试去连接的目标主机名。它可以是 IP也可以是域名还可以是一个被你写错的环境变量值。报错里出现1基本只可能是三种情况之一连接串里 host 字段写成了1比如psql -h 1 -U postgres -d postgres环境变量PGHOST被设置成了1程序代码里把某个编号变量当主机名拼进了连接串记住这个思路报错里出现的每一个值都是客户端真实想用的值。你不需要猜服务端有什么问题先盯住客户端到底在连谁。1.2 port 5432默认端口为什么会出现在报错里5432 是 PostgreSQL 的默认端口。看到port 5432很多人会下意识以为端口是不是被占用了防火墙是不是没放行——先别急着下结论。port 5432 failed只是陈述了一个事实客户端试图连目标的 5432 端口但失败了。至于失败原因是对端没监听网络不通被防火墙丢弃还是对端监听了别的位置报错本身没有说。所以这一段的正确用法是确认一下你的服务端到底在监听哪个端口。有时候你把端口改成了 5433但客户端连接串还写着 5432那当然是port 5432 failed。查看端口监听我一般用这几条命令# Linux ss -lntp | grep 5432 # Windows netstat -ano | findstr 5432如果输出里能看到 PostgreSQL 进程在0.0.0.0:5432或127.0.0.1:5432上监听说明端口这层没问题问题在别处。如果什么都没输出说明服务端根本没在这个端口上监听。1.3 failed postgres和尾部那个孤零零的P标题里failed postgres P明显是一个被截断的报错。完整的报错尾部大概长这样connection to server at 1, port 5432 failed: FATAL: password authentication failed for user postgres或者FATAL: database postgres does not exist这里有个很实用的经验复制报错必须整段复制最好连带时间戳和上下文一起复制。我见过太多人把报错尾部截掉然后在论坛上问为什么连接失败下面的人只能从残缺信息里猜。FATAL之后的描述才是真正的病根比如password authentication failed for user postgresTCP 通了密码不对。database postgres does not existTCP 通了认证也可能过了但连的库不存在。no pg_hba.conf entry for host 192.168.1.10, user postgres, database postgresTCP 通了但认证规则没匹配上。所以看报错要养成习惯先看connection to server at ... failed之后那一段FATAL或DETAIL那里通常才是真正的答案。1.4 引号、中文引号与手动转写误差标题里出现的1用的是中文引号“1”这个细节值得说一句。真实的 psql 报错里主机名两侧是英文引号。中文引号只有一种来源报错从网页、聊天记录、截图转写出来的时候被人为重新敲过一遍。这种二道转写非常容易引入误差。比如有人会把1看成l或者把0数字零看成O把-h参数漏掉。排查这类连接问题的时候一定以终端里复现的原始输出为准不要以聊天软件里的转写文本为准。这不是矫情是排错的基本纪律。2. 我建议的排错顺序进程、监听、网络、认证、密码很多新手一看到connection failed就先去重置密码这是最浪费时间的一种做法。我的习惯是严格按层级来从下往上、从内到外每层都用命令验证完再进下一层。顺序是这样的进程有没有起 → 端口在不在监听 → 网络通不通 → 认证规则拦没拦 → 密码对不对。2.1 第一层确认数据库进程有没有在跑这一步最简单但也最容易被忽略。服务的状态直接决定了后面所有层的判断。Linux 下systemctl status postgresql或者看进程ps aux | grep postgresWindows 下到服务管理器WinR 输入services.msc里看postgresql-x64-16之类的服务是否处于正在运行。macOS 下用 Homebrew 装的话brew services list还有一条所有平台通用的命令pg_isready专门用来探测 PostgreSQL 是否在某个端口就绪pg_isready -h 127.0.0.1 -p 5432如果输出accepting connections说明服务端进程活着并且接受了连接请求问题在更高层如果输出no response说明进程可能没跑。2.2 第二层确认端口在不在监听监听在哪块网卡进程起来不代表端口就对了。PostgreSQL 默认配置里listen_addresses往往是localhost意思是只监听本机回环地址。这样的配置下本机用127.0.0.1可以连局域网里的其他机器就连不上。看监听地址还是用前面那两条命令。这里重点解释一下监听地址的区别127.0.0.1:5432只让本机通过回环地址连接外部访问一律连不上。0.0.0.0:5432监听所有 IPv4 网卡只要防火墙允许局域网内的机器都能连。::5432监听 IPv6也要注意。如果你想允许远程连接需要改postgresql.conf里的listen_addresseslisten_addresses * # 监听所有网卡或者写具体的IP如 192.168.1.10注意改这个参数后必须重启 PostgreSQLreload 不生效。这个坑后面还会细说。2.3 第三层确认从客户端所在的网络能不能摸到这个端口这一层是在测网络路径而不是在测 PostgreSQL。我用telnet测 TCP 端口连通性telnet 192.168.1.10 5432如果连接被拒绝Connection refused说明端口没在听或者防火墙把端口挡了。如果卡住不动直到超时说明网络路径上有丢包或被防火墙静默丢弃这种情况最隐蔽。Windows 上 PowerShell 可以用Test-NetConnection 192.168.1.10 -Port 5432判断标准很简单在客户端机器上能telnet 通服务器的 5432才轮到怀疑认证和密码telnet 都不通问题在进程、监听或防火墙/安全组。别在密码上折腾半天最后发现是云服务器安全组没放行 5432。2.4 第四层确认pg_hba.conf的认证规则拦没拦你TCP 能通之后PostgreSQL 会按pg_hba.conf里的规则逐条匹配客户端的 IP、数据库名、用户名和连接方式。规则是自上而下第一条匹配者生效。常见的默认规则长这样# TYPE DATABASE USER ADDRESS METHOD host all all 127.0.0.1/32 scram-sha-256 host all all ::1/128 scram-sha-256这意味着默认情况下只允许本机回环地址用scram-sha-256认证方式连接。如果你用内网 IP192.168.1.50访问会直接被打回报错通常是FATAL: no pg_hba.conf entry for host 192.168.1.50, user postgres, database postgres, SSL off想要允许局域网访问需要在文件里加一行比如host all all 192.168.1.0/24 scram-sha-256改完pg_hba.conf不需要重启reload 即可systemctl reload postgresql或者在 psql 里执行SELECT pg_reload_conf();2.5 第五层确认密码和连接串参数前面四层都通了才轮到密码。PostgreSQL 的密码认证失败报错非常明确就是password authentication failed for user postgres。这种情况重置密码用su - postgres -c psql -c \ALTER USER postgres PASSWORD 你的新密码;\Windows 下可能需要先切到 postgres 用户再执行或者用 GUI 工具连上去改。密码的坑也很典型刚装完 PostgreSQL 时postgres用户的密码可能不是你以为的那个。Windows 安装器会让你设置密码Linux 用initdb初始化的集群默认走 peer 认证本地postgres系统用户可以直接免密登录但 TCP 连接就不一定了。所以密码不对很多时候不是改密码的问题而是认证方式和密码压根没对齐。3. 现场复盘当PGHOST被设成1之后这一节我完整复盘一次真实的排障过程从头到尾走一遍当时的思路。这种看到什么 → 想到什么 → 验证什么的链路比直接给答案更有参考价值。3.1 故障现象部署脚本半夜报错当时是凌晨一点多运维群里甩过来一条报错截图内容跟标题几乎一模一样psql: error: connection to server at 1, port 5432 failed: FATAL: password authentication failed for user postgres部署脚本是定时任务跑的每天都往 PostgreSQL 里同步数据前一天还是好的今天突然就失败了。报错里的FATAL: password authentication failed让人第一时间想到密码过期了被人改了——但实际上connection to server at 1这个诡异的主机名才是真正的异常信号。3.2 第一直觉错在哪我先去查了服务端我当时第一反应也是去查服务端进程正常、端口正常、防火墙正常、日志里干干净净没有任何来自1这个主机的连接记录。查了一圈发现数据库本身一切健康报错却还在。回头看 varchar 的这个主机名1才意识到问题根本不在服务端而在客户端。如果服务端日志里压根没有对应的连接尝试记录那多半是请求根本没到达数据库。这是一个非常关键的判断依据服务端日志是排错的照妖镜日志里没有你这条连接就别再盯着服务端看了。3.3 复现一次让报错自己说话为了复现我直接手动执行了脚本里的连接命令结果报错和线上完全一致。接下来用psql -E模式跑连接把连接参数打出来psql -E host1 port5432 dbnamepostgres userpostgres然后检查客户端环境变量env | grep -i pg输出结果让我愣了一下PGHOST1原来环境变量PGHOST被设置成了1。PostgreSQL 的 libpq 库里PGHOST环境变量优先级非常高连接串里不写host时它会自动读取PGHOST。所以 psql 看起来是在连一个叫1的主机实际是环境变量在作怪。3.4 根因确认环境变量把机器编号当成主机名了再往前翻发现是部署脚本里有一行把配置文件的机器编号读出来导出成了PGHOST原本应该是从配置里取数据库主机地址结果因为解析逻辑写错读到了配置里某行的第一个字段——而那个字段刚好是1机器分区编号。修复很简单把脚本里的导出逻辑改成读取真正的主机名然后清掉旧环境变量unset PGHOST再用psql连接一切恢复正常。3.5 复盘结论报错的提示都在原文里这个案例里最有意思的一点是报错从一开始就写得很清楚——server at 1。但我和同事都先被password authentication failed带跑了下意识去检查密码和服务端浪费了大概二十分钟。教训有三条报错里的每个字段都值得先读完尤其是server at ...这个位置。它告诉你的是客户端实际在连谁。服务端日志没有对应记录时问题基本在客户端或网络路径。环境变量在连接过程中的优先级很高排查时要主动检查PGHOST、PGPORT、PGUSER这类变量。从那以后我再遇到connection to server at ...报错第一件事就是打印客户端环境变量。4. 排障时容易踩的隐藏坑六个检查点除了核心的排错链路还有几个不做功课绝对会踩的坑这里单独整理出来。每个坑我都见过至少三次以上写出来帮你直接绕开。4.1 Linux下psql不经过5432端口socket优先在 Linux 上执行psql -U postgres -d postgres时如果没有显式指定-hlibpq 默认走的是 Unix domain socket而不是 TCP 5432。socket 连接走的认证规则在pg_hba.conf里是local开头的行根本不会触发host系列的 TCP 规则。这就导致一种迷惑现象本机能连把-h 127.0.0.1加上反而报错。原因往往是 socket 认证用的是peerTCP 认证走的是scram-sha-256两边的要求不一样。判断一个连接到底走没走 TCP看命令里有没有-h就行。建议统一用-h 127.0.0.1这种方式验证能避开 socket 和 TCP 的混乱。4.2 本机能连、换了机器就报错多半在listen_addresses很多人用 DBeaver 在本机连 PostgreSQL 没问题部署到服务器上从程序连就报Connection refused。原因几乎都是listen_addresses默认只监听 localhost。这个参数修改后必须重启实例不是 reload 就能生效的。重启命令systemctl restart postgresqlWindows 服务方式安装的话直接在服务管理器里重启服务。改完以后再用ss -lntp确认监听地址是不是变成了0.0.0.0:5432或你的内网 IP。4.3 pg_hba.conf改完不重启但要reloadpg_hba.conf和postgresql.conf的重载机制不一样。前者改完执行SELECT pg_reload_conf();或systemctl reload postgresql就能生效后者改完通常需要重启才能完全生效尤其是listen_addresses、port这类启动时读取的参数。最稳妥的做法是改postgresql.conf后重启改pg_hba.conf后 reload。如果不确定改的是哪个文件直接重启也不会有什么坏处只是生产环境注意业务中断窗口。4.4 IPv6规则没配localhost和127.0.0.1的差异localhost在现代系统里可能解析成::1IPv6也可能解析成127.0.0.1IPv4。很多人的pg_hba.conf里配了127.0.0.1/32的规则却没配::1/128结果用psql -h localhost连的时候连接走到了 IPv6 的::1被认证规则直接拒绝。表现就是-h 127.0.0.1能连-h localhost连不上。解决方法是把两条规则都加上host all all 127.0.0.1/32 scram-sha-256 host all all ::1/128 scram-sha-2564.5 连接串里把变量名当值用了这个坑在程序代码里特别常见。比如有人写conn psycopg2.connect( hosthost_id, # 变量名叫 host_id实际值是1 port5432, dbnamedb_name, userdb_user )如果host_id这个变量的含义是机器分组编号它的值就可能是1。传到 libpq 里客户端就真的去连一个叫1的主机。这类问题从代码审查阶段就能发现但往往要等部署环境里出现connection to server at 1这类诡异报错才会暴露。排查技巧把程序实际拼接出来的连接串原样打印出来看一眼。一步到位。4.6 多实例与端口占用同一台机器上可能同时跑着多个 PostgreSQL 实例比如一个系统自带的旧版本和一个手动安装的新版本还可能有 Docker 容器占着 5432 端口。你用psql连接的可能是 A 实例但 B 实例把端口占了就会出现服务看起来活着但连不上的奇怪现象。检查方法还是ss -lntp | grep 5432看监听进程到底是哪个二进制。如果有两个实例建议把不同实例放到不同端口避免互相打架。5. 把排错动作化成一个固定套路5.1 每次连接必带的调试开关psql有几个参数对排查非常实用psql -h 127.0.0.1 -p 5432 -U postgres -d postgres -E-E回显内部执行的 SQL 查询能看到 psql 自己跑了什么。-v ON_ERROR_STOP1遇到错误立即停止不会带歪后续输出。-w永远不提示输入密码配合PGPASSWORD环境变量做自动化脚本很方便。另外给psql加-d用 URI 格式连接会让参数更一目了然psql postgresql://postgres:密码127.0.0.1:5432/postgres?sslmodedisable这种格式里 host、port、dbname、user 全在一个字符串里报错时一眼就能看出哪段写错了。5.2 日志里能读到什么PostgreSQL 服务端日志是排错的下半场。默认情况下连接失败这种事件不一定都会写日志尤其是没到认证阶段就断掉的连接。所以要在配置文件里打开连接相关的日志参数log_connections on log_disconnections on log_line_prefix %m [%p] %q%u%d log_line_prefix里的%u是用户名%d是数据库名%p是进程号。打开日志后每当有人尝试连接都会在日志里留下记录。如果日志里完全没有对应 IP 的连接记录那结论非常明确请求没到数据库。日志位置一般在LinuxDebian/Ubuntu 系/var/log/postgresql/LinuxRHEL 系/var/lib/pgsql/数据目录/log/Windows 安装包C:\Program Files\PostgreSQL\版本号\data\log\5.3 快速诊断速查表下面这张表是我这些年总结出来的丢在书签里随时查。你看到报错文本直接对号入座报错文本特征大概率原因下一步动作connection to server at xxx, port 5432 failed: Connection refused服务没起、端口不监听或防火墙直接拒绝查进程、查ss -lntpconnection to server at xxx, port 5432 failed: No route to host网络路由不通、跨网段、安全组未放行查防火墙、路由、云安全组connection to server at xxx, port 5432 failed: timeout expired网络丢包、被安全策略静默丢弃用telnet/Test-NetConnection测连通性FATAL: password authentication failed for user xxxTCP 通了密码或认证方式不对重置密码、检查认证方式FATAL: no pg_hba.conf entry for host xxxTCP 通了pg_hba.conf没匹配当前客户端 IP改pg_hba.confreloadFATAL: database xxx does not existTCP 通了认证过了但连的数据库不存在确认库名server at 1这类诡异主机名客户端环境变量PGHOST或连接串写错检查env、连接串、文档变量赋值5.4 一个最省事的固定套路我自己的习惯是遇到连接报错先做三件事五分钟内基本能定位客户端这边打印环境变量env | grep -i pg同时打印连接串原文。服务端这边开日志确认log_connectionson然后看日志里有没有来自客户端 IP 的尝试记录。两边对照如果日志有记录看FATAL给的拒绝原因如果日志没有记录直接往网络和客户端参数方向查别在数据库服务上浪费时间。这三个动作做完问题的层级基本上就锁死了。剩下就是按层级打开对应配置修。最后再分享一个小技巧别小看pg_isready这一步。它最常见的用法是确认服务存活但它其实也接受-h -p -d -U这些参数可以直接指定客户端视角的探测目标。用它对同一套参数反复探测能直观感受到换了一个主机名结果从 accepting 变成 no response的差异。这个差异本身就是最好的教材——报错里的1不是玄学它就是你的连接参数被环境变量或者连接串污染后数据库在提醒你去检查客户端自己。