我正在使用python使用Psycopg2将csv数据转储到数据库中。为了使用COPY命令(文档:https://www.postgresql.org/docs/10/static/sql-copy.html),我需要授予Postgres对特定文件路径的权限。我需要授予特定目录路径路由和文件的权限,以避免出现以下错误:
COPY database.table_name FROM '/home/development_user/Documents/App/CSV/filename.csv' delimiter ',' csv header
ERROR: could not open file "/home/development_user/Documents/App/CSV/filename.csv" for reading: Permission denied
为简化操作,要将postgres添加到开发用户组。这样,postgres应该具有组读取权限,开发用户可以轻松地逐条路径定义组读取权限。我使用以下命令将postgres用户添加到development_user组,并验证它是否成功:
$ sudo usermod -a -G development_user postgres
$ groups postgres
postgres : postgres development_user
以下是使用namei -l [path]逗号的权限路径跟踪的输出
$ namei -l /home/development_user/Documents/App/CSV/filename.csv
drwxr-xr-x root root /
drwxr-xr-x root root home
drwxr-x--- development_user development_user development_user
drwxr-xr-x development_user development_user Documents
drwxr-xr-x development_user development_user App
drwxrwxr-x development_user development_user CSV
-rw-rw-r-- development_user development_user filename.csv
如您所见,development_user
组中的任何人现在都应该对路径中的所有目录具有读取(r
)和执行(x
)的权限,并且还必须进行读写最终文件的权限。如果postgres尝试与other
用户访问同一文件,则postgres将受development_user
目录的访问权限限制。
但是,当我尝试访问文件时,出现如上所述的权限错误。当我使用development_user
的读取和执行权限(如下面的命令)打开other
目录时,我能够读取文件为Postgres:
$ chmod o+rx /home/development
但是,我不想授予other
对development_user主目录的读取和执行权限,并且我看不到为什么postgres用户不能使用上面概述的组权限来访问相同的文件因为我将postgres添加到了development_user帐户。
任何想法,如果我的方法通过将postgres权限添加到用户组中来授予其读取文件的权限的方法可行吗?我不想使用此处提到的其他解决方案:(PostgreSQL - inconsistent COPY permissions errors)或此处(Postgres ERROR: could not open file for reading: Permission denied),它们建议通过将文件所有者设置为postgres:postgres来建议开放权限。或广泛开放目录权限,例如允许所有用户在开发主目录上读取和执行。我也不想在系统目录中创建另一个目录,并被迫按照此处的建议在该目录中保存文件:(psql ERROR: could not open file "address.csv" for reading: No such file or directory)。
答案 0 :(得分:1)
COPY命名文件或命令仅允许数据库超级用户使用, 因为它允许读取或写入服务器具有的任何文件 访问权限。
因此,进行复制的PostgreSQL用户必须是数据库超级用户。
您可以使用ALTER ROLE
命令来完成此操作:
ALTER ROLE <rolename> WITH SUPERUSER
也:
带有文件名的COPY指示PostgreSQL服务器直接读取 从文件或写入文件。该文件必须可由PostgreSQL访问 用户(服务器运行时使用的用户标识),并且必须指定名称 从服务器的角度来看。
...
在COPY命令中命名的文件可以由计算机直接读取或写入。 服务器,而不是客户端应用程序。因此,它们必须驻留在 或可供数据库服务器计算机而非客户端访问。
运行PostgreSQL的默认系统用户为postgres
。确保该用户有权访问要复制的文件。您可以使用命令sudo -i -u postgres
成为postgres用户,然后尝试查看文件来进行测试。
答案 1 :(得分:0)
我使用psychopg2游标类函数copy_expert(文档:http://initd.org/psycopg/docs/cursor.html)解决了这个问题的方法。 copy_expert允许您使用STDIN,因此无需为postgres用户颁发超级用户特权。
从Postgres COPY Docs(https://www.postgresql.org/docs/current/static/sql-copy.html):
请勿将COPY与psql指令\ copy混淆。 \ copy调用 从STDIN复制或复制到标准输出,然后在其中获取/存储数据 psql客户端可访问的文件。因此,文件可访问性和 \ copy时,访问权限取决于客户端而不是服务器 使用。
您还可以保留为访问development_user主文件夹和App文件夹而严格设置的权限。
sql = "COPY table_name FROM STDIN DELIMITER '|' CSV HEADER"
self._cursor.copy_expert(sql, open(csv_file_name, "r"))
答案 2 :(得分:0)
@jonnyjandles答案略有变化,因为这显示了一个神秘的self._cursor
-更典型的调用可能是:
copy_command = f"COPY table_name FROM STDIN CSV HEADER;"
with connection.cursor() as cursor:
cursor.copy_expert(copy_command, open(some_file_path, "r"))