说实话,看到这条报错,我第一反应是想起自己几年前第一次在Windows上装完PostgreSQL,拿着psql去连本机,结果对着黑窗口里那行英文懵了半天的场景。你贴出来的这个标题里写着connection to server at "1", port 5432 failed,这个"1"多半是终端显示或者复制过程把内容截断了,真实情况里更多见的是:
code复制connection to server at "localhost" (::1), port 5432 failed: FATAL: password authentication failed for user "postgres"
注意看中间那个(::1),这是整条报错里最关键、也最容易被忽略的线索。它几乎直接告诉了你:你的客户端把localhost解析成了IPv6环回地址,然后拿着这个地址去向5432端口发起连接,结果服务端不认账。
一个连接失败背后,往往不是单一原因,而是好几件事叠在一起。这篇文章我就把整条排查链路从头到尾走一遍,从服务端是否存活、监听地址配置,到pg_hba.conf认证规则,再到客户端连接串写法,把这个报错涉及的每个坑都翻出来讲透。不管你是刚装完pgsql的新手,还是从MySQL转过来被连接问题折磨的老手,照着这篇文章的顺序去查,大概率能定位到问题。
1. 报错背后藏着三层问题:先拆开"connection failed"看个明白
1.1 完整报错长什么样:被截断的信息才是最关键的
报错信息是数据库给你的第一份线索,但很多人看到connection failed就直接去百度了,没有仔细分析后面的内容。实际上PostgreSQL在连接失败时会告诉你非常具体的原因,关键是你要把报错看完整。
常见的完整报错有这么几类:
| 报错内容 | 含义 |
|---|---|
connection to server at "localhost" (::1), port 5432 failed: Connection refused |
服务端没有在监听,或者监听的地址不对,连接被系统拒绝 |
connection to server at "localhost" (::1), port 5432 failed: Connection timed out |
网络不通,常见于防火墙拦截、跨机器访问不通 |
connection to server at "localhost" (::1), port 5432 failed: FATAL: password authentication failed for user "postgres" |
网络和服务端都正常,但是密码认证没通过 |
connection to server at "localhost" (::1), port 5432 failed: FATAL: role "postgres" does not exist |
认证机制可能都通过了,但数据库里根本没有这个角色 |
connection to server at "localhost" (::1), port 5432 failed: fe_sendauth: no password supplied |
客户端没有提供密码,服务端要求密码认证但没收到密码 |
你看这几种情况,前面半句都一样,真正的差异在failed:后面的内容。所以排查的第一步,永远是把报错完整复现出来、完整截图,不要只看前半句。
1.2 三层问题模型:网络层、认证层、角色层
我把PostgreSQL连接失败的问题拆成三层,排查的时候就按这个顺序从下往上走:
第一层是网络层。这一层负责把客户端的请求送到PostgreSQL进程。如果PostgreSQL服务没启动、监听地址不对、端口被防火墙挡住,客户端根本到不了数据库那一层,报错就停留在Connection refused或者Connection timed out。
第二层是认证层。网络通了,PostgreSQL收到了你的连接请求,接下来pg_hba.conf会审查:你从哪个地址来、用什么用户名、要连哪个数据库、系统允许你用哪种认证方式。这一层卡住时,你看到的是password authentication failed、no pg_hba.conf entry for host这类报错。
第三层是角色与数据库层。认证通过了,PostgreSQL还要检查你要连接的角色是否存在、目标数据库是否存在、这个角色对这个数据库有没有权限。这一层的典型报错就是role "postgres" does not exist、database "mydb" does not exist。
很多人一上来就改密码、改配置文件,其实没搞清自己卡在哪一层。像标题这种包含port 5432 failed的报错,说明客户端至少解析出了目标地址,但连接请求的结果是失败的,这时候先不要急着怀疑密码,继续看后面的错误描述才能确定。
1.3 谁最常踩这些坑:新手与跨平台迁移场景
根据我遇到的案例,这类报错主要集中在三种场景:
第一种是第一次在Windows上装PostgreSQL,装完之后用psql去连,结果发现自己不知道密码是什么、服务没启动、或者安装时选的端口不是默认的5432。Windows安装包虽然会引导你设置超级用户密码,但很多人装完就忘了。
第二种是从MySQL迁移过来的人。MySQL默认端口3306,用户名通常就是root,连接串里写个localhost:3306就完事了。到了PostgreSQL这里,端口变成5432,默认超级用户是postgres,默认数据库也是postgres,每个环节都不一样,稍微搞错一个就连不上。
第三种是用Docker或者公司内网环境,经常出现容器里的PostgreSQL只监听了容器内部地址,宿主机访问不到;或者从开发机连测试服务器时,防火墙挡了5432端口。这种跨机器场景比本机连接更容易踩网络层的坑。
无论哪种场景,排查思路都是一样的:先确认服务端活着,再确认地址能通,最后看认证和角色。接下来我就按这个顺序拆。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 先确认PostgreSQL真的在跑:进程、端口、配置三板斧
2.1 端口和进程:Windows与Linux的检查命令
连接失败最直接的原因,就是PostgreSQL服务根本没起来,或者起来之后没有监听5432端口。我先说怎么查这个,因为这一步最快,也最基础。
在Windows上,打开PowerShell或CMD,执行:
code复制netstat -ano | findstr 5432
如果有输出,类似:
code复制TCP 127.0.0.1:5432 0.0.0.0:0 LISTENING 12345
TCP [::1]:5432 [::]:0 LISTENING 12345
说明PostgreSQL已经在监听5432端口。后面那个12345是进程PID,你可以用tasklist | findstr 12345确认这个进程是不是postgres.exe。
如果没有任何输出,大概率服务没启动。再用tasklist | findstr postgres看看进程是否存在。
在Linux上,命令类似:
code复制ss -lntp | grep 5432
或者
netstat -lntp | grep 5432
输出大概是:
code复制LISTEN 0 200 127.0.0.1:5432 0.0.0.0:* users:(("postgres",pid=5432,fd=7))
注意观察监听地址,127.0.0.1:5432说明只监听了IPv4的环回地址,[::1]:5432说明只监听了IPv6的环回地址。这个细节和后面的IPv6问题直接相关,先记住。
2.2 postgresql.conf里的监听配置:listen_addresses和port
如果服务在跑,但端口没监听,或者监听地址不是你预期的,那就得看配置文件了。PostgreSQL的主配置文件叫postgresql.conf,Windows安装版通常在C:\Program Files\PostgreSQL\16\data\postgresql.conf,Linux发行版通常在/etc/postgresql/16/main/postgresql.conf或者/var/lib/pgsql/16/data/postgresql.conf。
里面有两个参数跟你这次连接直接相关:
code复制listen_addresses = 'localhost' # 默认值,只监听本地
port = 5432 # 默认端口
listen_addresses决定PostgreSQL在哪些地址上监听连接请求。默认值是localhost,意思是只监听本机的环回地址,也就是127.0.0.1和::1。如果你把这一项改成了具体的IP,比如192.168.1.100,那客户端连接时指定的地址必须匹配这个IP,否则连接会被拒绝。
如果你改了port,那客户端连接时必须指定新端口,而不是5432。
修改postgresql.conf之后,需要重启PostgreSQL服务或者至少reload配置才会生效。listen_addresses和port属于需要重启的参数,不是reload就能生效的。这点要注意区分。
2.3 pg_isready:一条命令快速判断服务状态
每次连不上都去开终端敲netstat?稍微有点繁琐。PostgreSQL自带一个专门用来探测服务状态的小工具,叫pg_isready。
code复制pg_isready -h 127.0.0.1 -p 5432
如果服务正常,输出是:
code复制127.0.0.1:5432 - accepting connections
如果服务没起来,输出是:
code复制127.0.0.1:5432 - no response
这个命令的好处是它不做真正的连接认证,只检查目标端口有没有PostgreSQL在响应,所以不会因为密码错误或者角色不存在而误报。它也可以带超时参数:
code复制pg_isready -h 127.0.0.1 -p 5432 -t 5
-t指定超时秒数,单位是秒,适合写进脚本里做服务健康检查。
如果pg_isready显示accepting connections,但你的psql还是报错,那问题就往后移了,要么是地址解析不一样,要么是认证和角色的问题。
3. "localhost"不等于"127.0.0.1":IPv6解析才是这次报错的主角
3.1 为什么localhost会被解析成::1
开头我就说了,报错里的(::1)是很关键的线索。这里详细解释一下。
在现在的操作系统里,localhost这个主机名同时映射到两个地址:IPv4的127.0.0.1和IPv6的::1。你的程序发起连接时,系统会调用getaddrinfo来解析localhost,而不同的操作系统、不同的编程语言、不同的客户端库,解析结果的返回顺序可能不一样。
很多现代系统默认优先返回IPv6地址,也就是::1。这意味着你明明写的是localhost,实际去连接的却是IPv6地址。如果PostgreSQL服务端没有在IPv6地址上监听,连接就会失败。
为什么服务端明明在跑,客户端却连不上?因为PostgreSQL的listen_addresses = 'localhost'在解析时同样会尝试同时监听IPv4和IPv6,但某些环境、某些配置下,服务端最终只监听了IPv4的127.0.0.1。这时候客户端用IPv6的::1去连,系统层面就直接Connection refused了。
3.2 报错里的(::1)泄露了什么问题
回到你的报错,connection to server at "localhost" (::1), port 5432 failed,括号里的::1说明客户端解析localhost时拿到了IPv6地址。而连接失败,意味着服务端要么没有监听IPv6,要么IPv6连接被防火墙等东西挡住。
怎么区分呢?你可以做一个快速测试。用psql分别指定IPv4和IPv6地址去连接:
code复制psql -h 127.0.0.1 -p 5432 -U postgres
psql -h ::1 -p 5432 -U postgres
如果第一个能连、第二个失败,那就是服务端没有监听IPv6或者防火墙拦了IPv6。如果两个都失败,那问题可能在服务没起来或者认证环节。
我在一台Windows服务器上就遇到过这种情况:服务运行正常,netstat显示只监听了127.0.0.1:5432,没有[::1]:5432,而客户端psql默认用localhost解析到IPv6,于是一连一个准地失败。后来把客户端连接地址改成127.0.0.1就好了。
3.3 四种解法:改服务端、改客户端、改hosts、改配置
针对这种IPv6解析导致的连接问题,有几种解法和对应的取舍,我逐个说。
解法一:改服务端监听地址,让IPv6也能连
修改postgresql.conf:
code复制listen_addresses = '*'
*表示同时监听所有IPv4和IPv6地址。改完重启PostgreSQL,然后再用netstat检查,你会发现多了[::1]:5432的监听。这样做的好处是不用动客户端,坏处是*也会监听所有外部网卡,如果你不想让机器上其他网卡的连接进来,这个操作会扩大暴露面。更精准的写法是:
code复制listen_addresses = '127.0.0.1, ::1'
这样只监听本机回环地址,既兼容IPv4也兼容IPv6,外网网卡不监听,相对安全。
解法二:改客户端连接地址,直接用127.0.0.1
这是最简单直接的办法。psql里:
code复制psql -h 127.0.0.1 -p 5432 -U postgres -d postgres
GUI工具比如Navicat、DBeaver、pgAdmin,在连接配置里把主机名从localhost改成127.0.0.1就行。连接串里同理。
这个改法本质上绕过了localhost解析到IPv6的问题,不折腾服务端,适合快速解决问题。缺点是如果代码里写死主机名,那么每处都要改。
解法三:改系统的hosts文件,强制localhost走IPv4
Windows的hosts文件在C:\Windows\System32\drivers\etc\hosts,Linux在/etc/hosts。默认内容里有:
code复制127.0.0.1 localhost
::1 localhost
如果系统解析hosts时先遇到IPv6那条,就会走IPv6。你可以把::1 localhost这行注释掉,这样所有解析localhost的请求都只返回IPv4的127.0.0.1。
这个方案对整个系统所有程序都生效,一劳永逸,但改系统文件有一定风险,尤其对依赖IPv6的程序可能有影响,建议在测试环境验证后再动。
解法四:改连接串里的host参数
在代码、连接池、ORM框架里,把数据库连接地址明确写为127.0.0.1而不是localhost。这个方法最安全,不碰系统配置,只影响你自己的应用。后面第6章讲连接串的时候会再强调。
我个人在实际项目里,默认把连接串的主机名写成127.0.0.1而不是localhost,就是为了避免"localhost到底是IPv4还是IPv6"这种不确定性。数据库连接这种事,确定性比方便性重要得多。
4. pg_hba.conf认证失败与"role postgres does not exist"的真相
4.1 pg_hba.conf逐条匹配规则:谁允许谁从哪里连
网络层通了,接下来面对的就是认证层。PostgreSQL的客户端认证规则全部写在pg_hba.conf里,文件名里的hba是host-based authentication的缩写。
这个文件的路径和postgresql.conf一样,都在数据目录下。它的每一行是一个认证规则,结构是:
code复制连接类型 数据库 用户 来源地址 认证方法
例如:
code复制# 类型 数据库 用户 来源地址 认证方法
host all all 127.0.0.1/32 scram-sha-256
host all all ::1/128 scram-sha-256
local all postgres peer
规则从上到下逐条匹配。记住一个关键词:第一条匹配的规则生效,后面的规则不再看。比如你在上面写了host all all 0.0.0.0/0 trust,那下面再写几条更严格的规则,对于从IPv4来的连接来说,都不会被走到,因为前面那条trust已经先命中了。
这是新手最容易踩的坑:改了好几条规则,但实际生效的是第一条,后面改的根本没被用到。
4.2 认证方法怎么选:trust、scram-sha-256、peer
pg_hba.conf里认证方法决定"你怎么证明你是你",几种常见方法差别很大:
| 认证方法 | 行为 | 适用场景 |
|---|---|---|
trust |
完全信任,不需要密码,只要网络命中规则就直接放行 | 仅限本机调试、完全隔离的网络环境 |
scram-sha-256 |
需要用户名和密码,密码加盐哈希传输,是现在推荐的方式 | 几乎所有的生产环境、本地开发 |
md5 |
旧的密码哈希方式,兼容老客户端,但安全性不如scram | 需要兼容很老的客户端时 |
password |
明文密码传输,不推荐,除非网络本身是可信的 | 基本不推荐 |
peer |
用操作系统用户名作为数据库用户名,只在Unix socket连接下有效 | Linux本机local连接 |
生产环境推荐使用scram-sha-256。PostgreSQL 14以后,默认的密码加密方式也已经改成了scram-sha-256,如果你还在用md5,老版本客户端可能连不上。
4.3 role不存在和认证失败是两码事
很多人把password authentication failed和role "postgres" does not exist混为一谈,其实完全不是一回事。
password authentication failed for user "postgres"的意思是:用户postgres存在,密码校验没通过。你该做的是检查密码、重置密码、或者确认客户端提供的密码是否正确。
role "postgres" does not exist的意思是:数据库里根本没有叫postgres的角色,所以连密码都不用比对了,直接告诉你这个人不存在。
为什么会出现第二种情况?最常见的原因是:你用了某个不包含postgres超级用户的PostgreSQL发行版。比如某些Docker镜像,默认超级用户叫其他名字,或者你在Linux上用包管理器安装时,创建的超级用户名可能跟随系统用户。
解决方法是先找到实际存在的超级用户。可以用系统账户切换到PostgreSQL的管理员:
code复制sudo -u postgres psql
或者如果你知道其他超级用户的名称:
code复制psql -U <实际用户名> -d postgres
连进去之后,创建你需要的角色:
sql复制CREATE ROLE postgres WITH SUPERUSER LOGIN PASSWORD '你的密码';
如果连进去的权限都不够,或者你压根不知道任何能用的超级用户,那就需要启动单用户模式,这个我在下一小节说。
4.4 紧急自救:单用户模式或临时trust
如果你的数据库里没有可用角色,或者密码全忘了,有两个紧急处理办法。
方法一:临时修改pg_hba.conf为trust
把pg_hba.conf里对应的规则改成trust,重启服务,然后用你想要的那个用户连进去,创建好角色、改好密码,最后再把配置改回来。
具体操作:
- 备份一份pg_hba.conf。
- 找到对应你连接来源的那行,把认证方法改成
trust。 - 重启PostgreSQL服务。
- 用
psql -h 127.0.0.1 -U postgres -d postgres连接,此时应该不需要密码。 - 执行角色创建或密码修改。
sql复制ALTER USER postgres WITH PASSWORD '新密码';
- 还原pg_hba.conf,重启服务。
这个方法虽然有效,但trust会让任何人都能无密码连接,操作期间一定确保服务不对公网开放,而且操作完必须马上还原配置。
方法二:单用户模式启动PostgreSQL
单用户模式不会监听TCP端口,而是直接在当前终端里用一个独立的数据库进程操作数据目录,适合连服务都起不来的极端情况。先把服务停掉,然后执行:
在Linux上,切换成postgres系统用户:
code复制pg_ctl stop -D /var/lib/postgresql/16/main
postgres --single -D /var/lib/postgresql/16/main postgres
在Windows上,需要以管理员身份在CMD里找到安装路径:
code复制pg_ctl.exe stop -D "C:\Program Files\PostgreSQL\16\data"
postgres.exe --single -D "C:\Program Files\PostgreSQL\16\data" postgres
进入单用户模式会看到backend> 提示符,直接执行SQL:
code复制backend> CREATE ROLE postgres WITH SUPERUSER LOGIN PASSWORD '新密码';
然后按Ctrl+D退出,再正常启动服务。
单用户模式挺强大,但操作时要注意:不要在使用单用户模式期间再让其他进程访问数据目录,否则可能造成数据损坏。
修改pg_hba.conf后要reload,让配置生效,方法:
code复制pg_ctl reload -D 数据目录路径
或者psql里执行:
sql复制SELECT pg_reload_conf();
reload和restart不一样,reload只是重新读取配置文件,不会中断正在进行的连接,适合改pg_hba.conf这种权限配置。而listen_addresses、port这类参数改了必须restart,reload不会生效。
5. Windows环境下的完整排查链路
5.1 安装时就被忽略的密码和服务设置
Windows安装PostgreSQL时,有几个设置最容易埋下连接的坑。
第一个是超级用户密码。安装向导会要求你为postgres用户设置密码,但很多人随手填了一个,装完就忘了。等回头连不上,又想不起密码,只能走我上面说的忘记密码自救流程。建议装完之后立刻把密码写进密码管理器,或者用一条SQL验证一下:
sql复制SELECT current_user;
第二个是端口号。安装向导默认端口是5432,但如果机器上已经装了其他实例,或者端口被占用,安装向导会让你改一个新端口。装完之后如果你还按5432去连,自然连不上。安装完成后,查看安装目录下的postgresql.conf就能看到实际端口。
第三个是安装包自带的Stack Builder。安装完PostgreSQL主程序后,会弹出一个Stack Builder让你选装其他组件。如果你只是想快速跑起来,可以先跳过这个,它跟连接问题关系不大,别被它分散注意力。
5.2 服务启动的几种方式:服务管理器、pg_ctl、net start
Windows上PostgreSQL安装完会注册成一个Windows服务,服务名一般是postgresql-x64-16这种格式,后面的数字是版本号。
服务没启动是最常见的连接失败原因。启动服务有几种方式:
第一种,在PowerShell里用管理员权限执行:
code复制net start postgresql-x64-16
或者:
code复制Start-Service postgresql-x64-16
第二种,打开Windows服务管理器,按Win+R输入services.msc,找到PostgreSQL对应服务,右键启动。
第三种,用PostgreSQL自带的pg_ctl命令:
code复制pg_ctl.exe -D "C:\Program Files\PostgreSQL\16\data" start
这种方式不会注册成Windows服务,只是在前台或者后台启动一个数据库进程,适合测试和临时使用。如果希望以后开机自动启动,需要注册服务:
code复制pg_ctl.exe register -N postgresql-x64-16 -D "C:\Program Files\PostgreSQL\16\data"
服务启动失败的话,常见的报错原因包括:数据目录权限不对、端口被其他程序占用、postgresql.conf里有配置错误。这时去看日志比盲猜有用得多。
5.3 防火墙与远程连接:5432端口的放行问题
如果你是从另一台机器去连Windows上的PostgreSQL,除了服务端在监听外,还必须保证Windows防火墙放行了5432端口。
Windows防火墙默认会拦截外部来的连接请求。本地用psql连127.0.0.1没这个问题,那走的是回环接口,不经过防火墙。但局域网其他机器连过来,就会被拦。
放行端口可以用PowerShell管理员权限执行:
code复制netsh advfirewall firewall add rule name="PostgreSQL 5432" dir=in action=allow protocol=TCP localport=5432
如果服务端的listen_addresses只配了localhost,外部机器的连接请求同样进不来,服务端监听的地址必须是实际网卡的IP或者*。
如果你只想简单测试一下服务端端口通不通,可以从客户端机器上用:
code复制telnet 192.168.1.100 5432
能连通的话,telnet窗口一般是黑的或者显示连接成功;如果不通,会提示连接失败或者超时。
5.4 日志文件是最诚实的排错老师
我排查连接问题时,最依赖的不是猜,而是日志。PostgreSQL会把它收到每个连接请求的结果都写进日志里,你看了日志就知道服务端到底看到了什么。
Windows安装版默认日志在数据目录下的log文件夹里,比如:
code复制C:\Program Files\PostgreSQL\16\data\log
打开最新的日志文件,搜索你的连接时间对应的记录。常见关键字:
| 日志内容 | 含义 |
|---|---|
FATAL: password authentication failed for user "postgres" |
密码不对 |
FATAL: no pg_hba.conf entry for host "::1" |
这个来源地址没有匹配的pg_hba.conf规则 |
FATAL: role "postgres" does not exist |
角色不存在 |
LOG: could not bind to address ::1: Permission denied |
IPv6地址绑定失败,服务可能没监听IPv6 |
LOG: database system was shut down at ... |
数据库正常关闭,这是健康标志 |
看到日志内容,排错方向就明确了,不需要瞎猜。
在Linux上,日志位置根据发行版不同而变化,通常在/var/log/postgresql/下。
6. 客户端连接串与驱动:psql、Npgsql、环境变量优先级
6.1 psql命令行参数与默认行为
把服务端整套弄通之后,最后还得看客户端这边。很多人服务端没问题,但客户端连接串写错了,或者被环境变量干扰了。
psql是PostgreSQL自带的命令行客户端。最常用的参数就是-h、-p、-U、-d:
code复制psql -h 127.0.0.1 -p 5432 -U postgres -d postgres
注意几个psql的默认行为:
- 如果不指定
-h,psql会尝试通过Unix socket连接(Linux),Windows上则会用默认的localhost。 - 如果不指定
-p,默认端口就是5432。 - 如果不指定
-U,默认用户名是当前操作系统的用户名。Windows下可能是Administrator之类的,Linux下是你的登录用户名。 - 如果不指定
-d,默认数据库名等于用户名。
所以你在Windows上直接敲psql,相当于尝试以Windows当前用户名去连接名为该用户名的数据库,而不是你想当然的postgres。这也是很多人敲完psql之后一头雾水的原因。
psql连接时如果没有提供密码,会交互式提示你输入,而且输入时不会回显。如果想在脚本里避免交互,可以临时设置环境变量:
code复制set PGPASSWORD=你的密码
psql -h 127.0.0.1 -U postgres -d postgres
但注意,在命令行里明文写密码有安全风险,服务器上可以放在.pgpass文件里,这个后面说。
6.2 ADO.NET(Npgsql)连接串的写法
在.NET环境里连PostgreSQL,最常用的是Npgsql驱动。热搜里也有pgsql ado.net,说明不少人在Windows上用C#连PostgreSQL时踩了连接串的坑。
Npgsql的连接串大概长这样:
code复制Host=127.0.0.1;Port=5432;Database=postgres;Username=postgres;Password=你的密码;SSL Mode=Disable;
字段名和psql命令行参数是对应关系,不区分大小写。几个关键点:
Host要写IP,推荐直接写127.0.0.1,避免localhost解析到IPv6的问题。SSL Mode=Disable在本地开发时很常用。新版Npgsql默认会尝试SSL连接,如果服务端没有启用SSL或者配置不匹配,可能连接失败。如果确认是纯内网或本机测试,可以关闭SSL。Timeout字段控制连接超时时间,默认15秒,可以按需调整,比如设5秒让连接失败更快暴露。
如果是在appsettings.json里配置:
json复制{
"ConnectionStrings": {
"PostgresConnection": "Host=127.0.0.1;Port=5432;Database=postgres;Username=postgres;Password=your_password;SSL Mode=Disable;"
}
}
6.3 环境变量和密码文件:被忽略的干扰项
除了连接串本身,客户端还会读取一些环境变量,这些环境变量的优先级不低,经常造成"配置明明是对的,但他连的还是别的地方"这种怪事。
psql和libpq相关的关键环境变量:
| 环境变量 | 作用 | 优先级 |
|---|---|---|
PGHOST |
覆盖默认连接主机名 | 高于psql不带-h时的默认值 |
PGPORT |
覆盖默认连接端口 | 高于默认5432 |
PGUSER |
覆盖默认用户名 | 高于psql不带-U时的默认值 |
PGPASSWORD |
提供默认密码 | 避免交互提示 |
PGDATABASE |
覆盖默认数据库名 | 高于psql不带-d时的默认值 |
也就是说,如果你在环境变量里设了PGHOST指向某台服务器,然后命令行里不写-h,psql就会连到那台服务器,而不是你以为的本机。查问题的时候,先执行:
code复制echo %PGHOST%
echo %PGPORT%
echo %PGUSER%
Linux上则是:
code复制echo $PGHOST
确保没有残留的干扰变量。
密码文件方面,libpq还支持读取.pgpass文件来提供密码,避免每次连接都交互输入。Windows上这个文件叫pgpass.conf,位置在%APPDATA%\postgresql\pgpass.conf,Linux上是~/.pgpass。格式是:
code复制主机:端口:数据库:用户名:密码
比如:
code复制127.0.0.1:5432:postgres:postgres:mysecret
文件权限要注意,Linux上需要设成600,否则libpq会拒绝读取。
如果你发现连接时密码总是莫名其妙地不对,检查一下是不是pgpass.conf里的旧密码把新密码覆盖了。
最后再分享一个我个人处理连接问题时的小习惯:无论是psql、GUI工具还是应用代码,连接参数里的主机名我统一写127.0.0.1而不是localhost。别小看这个习惯,它帮我在很多场合躲过了IPv6解析带来的隐性连接失败。数据库连接这种东西,参数越明确,排障就越省心。如果你也正在被这个报错折磨,我建议你先停止反复试密码,静下来把报错从后往前读一遍,按这篇文章的顺序去查,问题往往比你想象的要简单。
