在 Linux 6.0.12-arch1-1 上将 COPY 命令与 postgresql 14.6-1 结合使用时遇到权限问题

在 Linux 6.0.12-arch1-1 上将 COPY 命令与 postgresql 14.6-1 结合使用时遇到权限问题

大家好:)我是菜鸟,正在尝试使用 arch linux 内核上的 postgresql 14.6-1 学习 sql:6.0.12-arch1-1,我正在阅读的书的当前主题让我执行这个命令

COPY char_data_types TO '/home/user/path/to/file.txt'
    WITH (FORMAT CSV, HEADER, DELIMITER '|');

但我收到了这个错误:

[2022-12-13 18:49:30] [42501] ERROR: could not open file "/home/user/path/to/file.txt" for writing: Permission denied
[2022-12-13 18:49:30] Hint: COPY TO instructs the PostgreSQL server process to write a file. You may want a client-side facility such as psql's \copy.

我以为我可以通过摆弄我试图写入的目录权限来解决这个问题,所以我尝试了几件事,比如先创建文件,然后允许所有人对它chmod a+rwx或我试图让 postgres 创建文件的目录具有写入权限,甚至创建了一个目录并执行了chown directory postgres; chgrp directory postgress但仍然出现错误。

postgres有趣的是,当我以用户身份登录时,sudo -iu postgres我似乎无法访问 之外的任何目录/var/lib/postgres/data(无权访问的意思是无法使用 写入文件touch,甚至无法实际 cd 进入 中的任何子目录/home)。我还通过执行以下操作将用户添加postgresuserswheel组,usermod -aG users postgres; usermod -aG wheel postgres;但仍然出现同样的错误,我甚至给了它 root 访问权限,但仍然没有运气。

在 postgres 方面,我在 psql shell 中执行了几个 postgres 命令,这些命令是我在网上找到的,我认为可以帮助运行几个GRANT命令。我记不清所有命令了,但这是我运行时 psql 的输出\du

postgres=# \du
                                                 List of roles
 Role name |                         Attributes                         |              Member of               
-----------+------------------------------------------------------------+--------------------------------------
 malup     | Superuser                                                  | {pg_read_all_data,pg_write_all_data}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {pg_read_all_data,pg_write_all_data}

但仍然有同样的错误。

我找到了一个快速建议,只需将文件写入/tmp目录,这样我就不必处理权限问题。当我这样做时,我没有收到错误,但由于某种原因该文件不存在。我不知道发生了什么。

我发现成功让命令实际写入文件的唯一方法是,如果我在命令中COPY传入目录:postgres/data

COPY char_data_types TO '/var/lib/postgres/data/file.txt'
    WITH (FORMAT CSV, HEADER, DELIMITER '|');

有没有办法真正允许这个 postgres 写入系统中的其他用户目录?我认为这不再是与文件权限相关的问题。

我也知道我可以使用\copypsql 但我想从 sql 脚本中尝试它。

答案1

如果不使用/tmp,则允许从 root 向下访问 postgres 服务器用户,而不仅仅是父目录

Postgres 可以从/tmp目录中读取,但 50+ 2GB 的解压文件放不下。改用 /home/user 下的子目录。为了让 PostGRES 服务器能够读取此文件COPY FROM,需要授予从树到根目录的权限/,而不仅仅是父目录。

禁用 SeLINUX¹

对于 Redhat RHEL 8.8 上的相同问题:

SQL Error [42501]: ERROR: could not open file "/tmp/a.csv" for reading: Permission denied Hint: COPY FROM instructs the PostgreSQL server process to read a file. You may want a client-side facility such as psql's \copy. 我尝试移动文件,以postgres超级用户身份操作,但没有任何效果,直到禁用 SELinux

COPY FROM直接在服务器上加载是使该解决方案可行的关键。这些庞大的 100Gb 表直接从服务器加载速度最快,这就是为什么客户端psql \copy或尝试通过管道传输到云服务器是不可行的。事实证明,与此 Ryzen 7 / AM5 nvmE 裸机解决方案相匹配所需的 PostGRESQL PaaS 设置对于每月发生一两次的批量转换而言过于昂贵。

¹安全注意事项. (在这种情况下,它是私有网络上的离线专用服务器,仅运行以消化和分析非常大的表格,然后关闭。)

答案2

(我所说的没有访问权限是指无法使用 touch 写入文件,甚至无法通过 cd 进入 /home 中的任何子目录)。我还通过执行 usermod -aG users postgres; usermod -aG wheel postgres; 将 postgres 用户添加到用户和 wheel 组,但仍然是同样的错误,我甚至给了它 root 访问权限,但仍然没有运气。

您基本上已经自己解释了这个问题。postgres 用户无法 cd 进入所需的目录,因为父目录拒绝 postgres 用户访问。

如果你的文件位于 /test/foo/bar/file.txt 中,你就无法访问 file.txt,即使用户有权访问 bar/,只要用户无权访问 foo/

最简单的解决方案是将输出写入“公共”目录(例如 /tmp)或某些自定义特殊目录(例如 /var/mycustomscript/export.sql),并授予 postgres 用户访问该目录的权限。

强烈 不鼓励您将此类内容放在主目录之类的地方。

总的来说,你似乎仍然缺乏一些关于 liux 文件权限的知识(没关系,每个人都必须开始,我们不是生来就有这种智慧的 :D )。我鼓励你尝试阅读它是如何工作的 :)

答案3

对于仍在研究此问题的其他任何人:这似乎是所有操作系统上遵循此类教程的用户的常见问题。Linux 中的主要问题是似乎您真的可以让 postgres 用户访问 /home/ 目录。我不确定 op 在 /tmp 文件夹中遇到了什么问题。但是,就我而言,简单的解决方案是:1. 将 CSV 移动到 /tmp/。2. 右键单击​​ CSV 并转到属性,设置权限:对于“其他”访问:“读取和写入”。

相关内容