3

我正在尝试将COPY文件放入 PostgreSQL 中的表中。表所有者是postgres,文件所有者是postgres.

该文件位于/tmp.

我仍然收到错误消息:

无法打开文件“/tmp/file”进行阅读:权限被拒绝

我不明白我做错了什么,因为我发现的所有帖子都说如果我有文件/tmp并且所有者是,postgres那么COPY命令应该可以工作。

4

2 回答 2

6

猜测:您使用的是 Fedora、Red Hat Enterprise Linux、CentOS、Scientific Linux 或其他默认启用SELinux的发行版之一。

在您的特定操作系统/版本上,PostgreSQL 的 SELinux 策略不允许服务器读取 PostgreSQL 数据目录之外的文件,或者该文件是由目标策略涵盖的服务创建的,因此它具有 PostgreSQL 不是的标签允许读取。

您可以通过以 root 身份运行来确认这是否是问题所在:

setenforce 0

然后重新测试。跑:

setenforce 1

测试后重新启用 SELinux。setenforce不是永久性的;无论如何,SELinux 将在重新启动时自动重新启用。永久禁用 SELinux 通常不是解决此类问题的好方法;如果您确认问题是 SELinux,则可以进一步探索。


由于您没有指定您正在使用的操作系统或版本、PostgreSQL 版本、您正在运行的确切命令、ls -al文件、\d+表格等,因此很难提供更多细节,或者知道这是否更多比猜测。尝试更新您的答案以包括所有这些和ls --lcontext文件。

于 2012-09-05T09:05:46.540 回答
1

COPY使用文件名指示 PostgreSQL 服务器直接读取或写入文件。该文件必须可由 PostgreSQL 用户(服务器运行的用户 ID)访问,并且必须从服务器的角度指定名称。(来源:postgresql 文档

因此,运行 postgresql 服务器的 unix 用户(即不是您的用户!)应该可以读取(或写入)该文件。可以肯定的是,你可以尝试运行 sudo -u postgres head /tmp/test.csv(假设你被允许使用sudo并且假设数据库用户是postgres)。

如果失败,则可能是与 SELinux 相关的问题(如 Craig Ringer 所述)。在 Red Hat/Fedora/CentOS、Scientific Linux、Debian 和其他人使用的最常见的 SELinux 策略(“目标”参考策略)下...... postgresql 服务器进程受到限制:它只能读取/写入几种文件类型.

/var/log/audit/audit.log由于 donaudit 规则,拒绝可能不会记录在 auditd 的日志文件 ( ) 中。所以通常的 SELinux 快速测试适用,例如:通过运行阻止 SELinux 限制任何进程getenforce;setengorce 0;getenforce,然后测试 postgresql 的COPY. 然后通过运行重新激活SELinux setenforce 1(这个命令修改的是运行状态,不是配置文件,所以SELinux在重启后会激活(Enforcing)。

解决此问题的正确方法是更改​​要加载的文件的 SELinux 上下文。快速破解是运行:

chcon -t postgresql_tmp_t /tmp/a.csv

但是,如果重新标记 hte 文件系统或创建新文件,则此文件标记将无法保留。您需要创建一个带有 SELinux 文件上下文映射的目录:

which semanage || yum install policycoreutils-python
semanage fcontext -a -t postgresql_tmp_t '/srv/psql_copydir(/.*)?'
mkdir /srv/psql_copydir
chmod 750 /srv/psql_copydir
chgrp postgres /srv/psql_copydir
restorecon -Rv /srv/psql_copydir
ls -Zd /srv/psql_copydir

在该目录中创建的任何文件都应自动具有正确的文件上下文,以便 postgresql 服务器可以读取/写入它。

(要检查 postgres 正在运行的 SELinux 上下文,请运行ps xaZ | grep "postmaste[r]" | grep -o "[a-z_]*_t",它应该打印postgresql_t。要列出postgresql_t可以写入的上下文类型,请使用sesearch -s postgresql_t -A | grep ': file.*write'. 该命令sesearch属于setools-consoleRPM 包)。

于 2015-02-18T22:31:12.903 回答