我正在尝试将COPY
文件放入 PostgreSQL 中的表中。表所有者是postgres
,文件所有者是postgres
.
该文件位于/tmp
.
我仍然收到错误消息:
无法打开文件“/tmp/file”进行阅读:权限被拒绝
我不明白我做错了什么,因为我发现的所有帖子都说如果我有文件/tmp
并且所有者是,postgres
那么COPY
命令应该可以工作。
我正在尝试将COPY
文件放入 PostgreSQL 中的表中。表所有者是postgres
,文件所有者是postgres
.
该文件位于/tmp
.
我仍然收到错误消息:
无法打开文件“/tmp/file”进行阅读:权限被拒绝
我不明白我做错了什么,因为我发现的所有帖子都说如果我有文件/tmp
并且所有者是,postgres
那么COPY
命令应该可以工作。
猜测:您使用的是 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
文件。
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-console
RPM 包)。