如何在WSL中连接到Windows的PostgreSQL数据库

52

我在我的Windows计算机上运行Postgres 11服务。我该如何从WSL连接到这个数据库?

当我尝试su - postgres时:

postgres@LAPTOP-NQ52TKOG:~$ psql 
psql: could not connect to server: No such file or directory 
        Is the server running locally and accepting
        connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"

它正在尝试连接到WSL中的Postgres。我不想使用以下命令来运行Ubuntu Postgres: sudo /etc/init.d/postgresql start


Postgres在WSL内的Windows上运行吗? - user330315
6个回答

97

WSL2动态分配IP地址给Windows主机,而这些IP地址可以在不重启Windows的情况下发生变化(请参见下面的注释)。因此,要可靠地连接,我们需要:

  1. 允许Windows和Postgres接受来自WSL2 IP地址范围的连接(默认情况下不允许)
  2. 从WSL2中,当通过psql连接时确定Windows/Postgresql主机的IP地址(该地址是动态的)。我们将通过.bashrcalias使其方便。

不幸的是,我找不到WSL2 IP地址范围的确切规范。从几次测试/重启中,看起来WSL2主要在172.*.*.*的范围内分配IP地址,但我偶尔被分配了192.*.*.*,因此在配置防火墙和Postgres时,我们将使用这些地址范围。

为WSL2 IP地址添加Windows防火墙入站端口规则:

  1. 打开 Windows Defender高级安全性防火墙
  2. 点击 新建规则...
  3. 选择端口作为规则类型
  4. 选择TCP,对于特定本地端口输入5432
  5. 选择 允许连接。从WSL2连接不会安全,因此不要选择安全选项
  6. 至少选择 公用网络。也可以选择 域网络专用网络。只有选了 公用网络,我才能连接成功
  7. 命名规则,例如 Postgres - connect from WSL2,并创建它
  8. 右键新创建的规则,选择 属性,然后点击 范围 选项卡
  9. 远程IP地址 下,选择 这些IP地址,然后点击 添加...,并输入范围172.0.0.1172.254.254.254
  10. 重复步骤9,为IP地址范围192.0.0.1192.254.254.254添加规则
  11. 点击 应用 然后 确定
  12. 确保规则已启用

配置Postgres接受来自WSL2 IP地址的连接

假设Postgresql默认安装/设置在Windows上,以下文件位于 C:\Program Files\PostgresSQL\$VERSION\data目录下

验证postgresql.conf是否有以下设置:

listen_addresses = '*'

这应该已经设置为'*',所以这里不需要进行任何操作。

更新pg_hba.conf以允许来自WSL2范围的连接,例如对于PostgreSQL 12:

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
host    all             all             172.0.0.0/8             md5
host    all             all             192.0.0.0/8             md5

如果使用Postgresql 13+,应该使用scram-sha-256作为方法。

重启Postgres使更改生效。这可以通过Windows Services应用程序或以管理员特权从cmd中完成,例如对于Postgresql 12:

net stop postgresql-x64-12
net start postgresql-x64-12

WSL Shell Conveniences

在WSL中,将以下内容添加到您的~/.bashrc或类似文件中:

# Add DNS entry for Windows host
if ! $(cat /etc/hosts | grep -q 'winhost'); then
  echo 'Adding DNS entry for Windows host in /etc/hosts'
  echo '\n# Windows host - added via ~/.bashhrc' | sudo tee -a /etc/hosts
  echo -e "$(grep nameserver /etc/resolv.conf | awk '{print $2, "   winhost"}')" | sudo tee -a /etc/hosts
fi

然后重新加载您的 .bashrc 更改: source ~/.bashrc

用法

psql -h winhost -p 5432 -U postgres

注意:

  • WSL2分配给Windows主机的IP地址与网络中物理Windows计算机分配的IP地址不同。WSL2使用vEthernet连接。
  • 您可以通过控制面板\网络和 Internet\网络连接检查vEthernet连接。
  • 请注意,查看IPv4属性时,IP地址将显示为静态设置,但实际上并非如此!尝试重新启动计算机,再次检查IPv4属性。
  • 如果有一天无法连接到Postgres,请检查防火墙规则中winhost是否在IP地址范围内。可能是WSL分配了我们没有预期的IP地址!

1
要在PosgreSQL v13上使其正常工作,需要进行以下更改:
  1. 删除 listen_addresses = '*' ,因为这会阻止postgresql启动。
  2. pg_hba.conf 中,我将 METHOD 设置为 scram-sha-256
同时注意,默认情况下,PosgreSQL 13 监听端口为 5433
- thiagodebastos
3
截至2021年10月,这可能是唯一有效的解决方案。仅使用nameserver作为主机名无法从wsl2中的Windows连接到Postgres。 - Hiroki
2
非常好的回答。在我的情况下,由于我的计算机是Windows 11 Home版,我必须通过建议的方法启用hypervisor,方法在这里:https://beebom.com/how-enable-hyper-v-windows-11-home/。默认情况下,Windows 11 Home似乎没有启用和提供此功能。 - M. Andersen
3
您的IP范围太大,包含了公共地址。可能的私有网络块是172.16.0.0/12192.168.0.0/1610.0.0.0/8。但是,您的局域网或域网络很可能正在使用其中一个。 - OrangeDog
2
要在WSL中获取Windows机器的IP地址,请执行dig +short ${HOSTNAME}.local命令。 - OrangeDog
1
要获取WSL环境的IP地址,请执行ip address show eth0 - OrangeDog

21
在WSL2中,您需要使用主机IP进行连接。 要获取主机IP,请运行以下命令: grep nameserver /etc/resolv.conf | awk '{print $2}' 然后,您需要在“Windows Defender高级安全防火墙”中允许TCP 5432入站规则。
我自己做了一些工作PS。您仍然需要在防火墙中允许TCP 5432。 将以下内容添加到~/.bashrc文件中: cat /etc/hosts | grep 172.; test $? -eq 0 && $1 || echo -e "$(grep nameserver /etc/resolv.conf | awk '{print $2, " host"}')\n$(cat /etc/hosts)" | sudo tee /etc/hosts 如果之前不存在(通常在重新启动wsl或计算机时发生),它会将主机IP追加到/etc/hosts中。 然后,
psql -h host -p 5432 -U postgres

13

明确指定您的主机、端口和用户名,例如:

psql -h 127.0.0.1 -p 5432 -U postgres

14
我遇到了psql: error: could not connect to server: Connection refused Is the server running on host "localhost" (127.0.0.1) and accepting TCP/IP connections on port 5432?的错误提示。不过,在Windows控制台中,相同的命令可以正常工作。 - RAM237

3

对我而言可行的方法如下:

  • 修改pg_hba.conf文件以便监听所有接口:host all all 0.0.0.0/0 trust
  • 打开postgresql的防火墙
  • /etc/hosts中使用指向主机IP的其中一个主机名。对于我来说,这个主机名是:host.docker.internal

1
这个问题可以有两种可能的解决方式:
1. 明确指定主机和用户名。 2. 使用本地套接字连接。
psql -h localhost -U postgres

或者

导航到runpsql.sh文件并运行查询

/Library/PostgreSQL/14/scripts/runpsql.sh

现在输入密码(如果需要),运行psql查询


0
我发现WSL 2确实会出现这个错误: psql: 错误: 无法连接到服务器"localhost" (127.0.0.1),端口5432失败: 拒绝连接 该服务器是否在该主机上运行并接受TCP/IP连接?
但是WSL 1则没有出现这个问题。
我在WSL 1和WSL 2上分别运行了两个不同的Ubuntu发行版,并在WSL 1中测试了连接,连接成功。
我降级了另一个版本并重新测试,也成功了。然后我升级回来,又出现了错误。
WSL 2是一个更完整的(请参考这里... https://learn.microsoft.com/en-us/windows/wsl/compare-versions),它是一个完整的Linux内核和托管的虚拟机,而WSL 1则不是。
如果你和我一样,对于测试的要求不是那么严格(而且对于我来说,在工作笔记本上切换到管理员用户来处理防火墙和Postgres设置是一个费力的过程),而且你只需要像我一样从Linux进行测试,那么你可以安装另一个WSL并将其保留在1版本甚至降级。需要注意的是,这样做将不支持Rancher Desktop,因为它需要WSL 2。Docker Desktop会安装WSL 2,所以这不应该成为一个考虑因素。
在这里可以找到更多关于查看你的WSL版本等信息的信息。

https://learn.microsoft.com/en-us/windows/wsl/compare-versions

HTH.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接