psql 可以连接到 unix 域套接字,但具有相同参数的 py-postgresql 得到“权限被拒绝”

Mil*_*osz 8 postgresql unix-socket python-3.x py-postgresql

问题描述:

我的系统用户是milosz,它映射到project_great中的PostgreSQL 用户pg_ident.conf。我正在使用对等身份验证通过 unix 域套接字连接到 PostgreSQL 数据库。此连接方法在使用 时有效,但在使用 Python 脚本中的相同参数psql时则失败。py-postgresql

在这里,我使用以下命令成功连接到数据库psql

$ psql -U project_great \
>      -d project_great \
>      -h /var/run/postgresql
psql (9.3.4)
Type "help" for help.

project_great=> 
Run Code Online (Sandbox Code Playgroud)

这是database_test.py

#!/usr/bin/env python3

import postgresql

params = {
    'user':     'project_great',
    'database': 'project_great',
    'unix':     '/var/run/postgresql',
}

connection = postgresql.open(**params)
Run Code Online (Sandbox Code Playgroud)

在这里,我尝试通过运行连接到数据库./database_test.py

$ ./database_test.py 
Traceback (most recent call last):
  File "./database_test.py", line 11, in <module>
    sys.exit(main(sys.argv))
  File "./database_test.py", line 13, in main
    connection = postgresql.open(**params)
  File "/home/milosz/devel/project_great/.virtualenv/lib/python3.3/site-packages/postgresql/__init__.py", line 94, in open
    c.connect()
  File "/home/milosz/devel/project_great/.virtualenv/lib/python3.3/site-packages/postgresql/driver/pq3.py", line 2422, in connect
    self._establish()
  File "/home/milosz/devel/project_great/.virtualenv/lib/python3.3/site-packages/postgresql/driver/pq3.py", line 2548, in _establish
    self.typio.raise_client_error(could_not_connect, creator = self, cause = exc)
  File "/home/milosz/devel/project_great/.virtualenv/lib/python3.3/site-packages/postgresql/driver/pq3.py", line 514, in raise_client_error
    raise client_error
postgresql.exceptions.ClientCannotConnectError: could not establish connection to server
  CODE: 08001
  LOCATION: CLIENT
CONNECTION: [failed]
  failures[0]:
    socket'/var/run/postgresql'
    Traceback (most recent call last):
      File "/home/milosz/devel/project_great/.virtualenv/lib/python3.3/site-packages/postgresql/protocol/client3.py", line 136, in connect
        self.socket = self.socket_factory(timeout = timeout)
      File "/home/milosz/devel/project_great/.virtualenv/lib/python3.3/site-packages/postgresql/python/socket.py", line 64, in __call__
        s.connect(self.socket_connect)
    PermissionError: [Errno 13] Permission denied

    The above exception was the direct cause of the following exception:

    postgresql.exceptions.ConnectionRejectionError: Permission denied
      CODE: 08004
      LOCATION: CLIENT
CONNECTOR: [Unix] pq://project_great@[unix::var:run:postgresql]/project_great
  category: None
DRIVER: postgresql.driver.pq3.Driver
Run Code Online (Sandbox Code Playgroud)

由于两个连接的参数表面上是相同的,并且我对套接字及其包含目录的权限相当开放,所以我不知道问题是什么。使用 TCP 并不是一个解决方案;我想使用 unix 域套接字。py -postgresql 文档表明使用 unix 域套接字进行连接应该可以工作。

配置:

pg_hba.conf:

# TYPE   DATABASE  USER      ADDRESS             METHOD  OPTION
local    all       all                           peer    map=default
Run Code Online (Sandbox Code Playgroud)

pg_ident.conf:

# MAPNAME       SYSTEM-USERNAME         PG-USERNAME
default         postgres                postgres
default         milosz                  project_great
Run Code Online (Sandbox Code Playgroud)

postgresql.conf:

...
port = 5432
unix_socket_directories = '/var/run/postgresql'
...
Run Code Online (Sandbox Code Playgroud)

以下是我的套接字目录的权限:

$ ll /var/run/postgresql/
total 8
drwxrwsr-x  2 postgres postgres 100 May 17 00:20 ./
drwxr-xr-x 31 root     root     900 May 17 00:41 ../
-rw-r--r--  1 postgres postgres   5 May 17 00:20 9.3-main.pid
srwxrwxrwx  1 postgres postgres   0 May 17 00:20 .s.PGSQL.5432=
-rw-------  1 postgres postgres  70 May 17 00:20 .s.PGSQL.5432.lock
Run Code Online (Sandbox Code Playgroud)

PostgreSQL用户project_great已被授予数据库的所有权限project_great,并且用户和数据库都存在。

我没有~/.pgpass

环境:

  • 乌班图13.10
  • Python 3.3
  • PostgreSQL 9.3
  • py-postgresql 1.1.0

Mil*_*osz 9

Craig Ringer建议在下面运行这两个程序,strace以查明系统调用是否存在相关差异。我搜索/var/run/postgresql并发现 while psqlrunconnect像这样:

connect(4, {sa_family=AF_LOCAL, sun_path="/var/run/postgresql/.s.PGSQL.5432"}, 110) = 0
Run Code Online (Sandbox Code Playgroud)

./database_test.pyconnect像这样跑:

connect(4, {sa_family=AF_LOCAL, sun_path="/var/run/postgresql"}, 21) = -1 EACCES (Permission denied)
Run Code Online (Sandbox Code Playgroud)

问题就出在哪里。

虽然psql需要unix 域套接字所在目录的路径py-postgresql,但需要套接字的完整路径。因此,修复方法是修改database_test.py为如下所示:

#!/usr/bin/env python3

import postgresql

params = {
    'user':     'project_great',
    'database': 'project_great',
    'unix':     '/var/run/postgresql/.s.PGSQL.5432',
}

connection = postgresql.open(**params)
Run Code Online (Sandbox Code Playgroud)

老实说,我因为没有尝试完整路径作为早期的调试步骤而感到愚蠢!

  • 请将其作为错误报告给“py-postgresql”。它应该与所有 libpq 客户端一致,例如 `psql`、`psycopg2` 等(顺便说一句,如果没有充分的理由,我强烈建议使用 `psycopg2` 而不是 `py-postgresql`)。 (2认同)