COPY
with a file name instructs the PostgreSQL server to directly read from or write to a file. The file must be accessible by the PostgreSQL user (the user ID the server runs as) and the name must be specified from the viewpoint of the server. (source: postgresql documentation)
So the file should be readable (or writable) by the unix user under which postgresql server is running (i.e not your user!). To be absolutly sure, you can try to run sudo -u postgres head /tmp/test.csv
(assuming you are allowed to used sudo
and assuming the database user is postgres).
If that fails, it might be an issue related to SELinux (as mentioned by Craig Ringer). Under the most common SELinux policy (the "targeted" reference policy), used by Red Hat/Fedora/CentOS, Scientific Linux, Debian and others... the postgresql server process is confined : it can only read/write a few file types.
The denial might not be logged in auditd's log file (/var/log/audit/audit.log
) due to a donaudit rule. So the usual SELinux quick test apply e.g: stop SELinux from confining any process by running getenforce;setengorce 0;getenforce
, then test postgresql's COPY
. Then re-activate SELinux by running setenforce 1
(this command modify the running state, not the configuration file, so SELinux will be active (Enforcing) after reboot.
The proper way to fix that is to change the SELinux context of the file to load. A quick hack is to run:
chcon -t postgresql_tmp_t /tmp/a.csv
But this file labelling will not survive if hte filesystem is relabel or if you create a new file. You will need to create a directory with an SELinux file context mapping :
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
Any file created in that directory should have the proper file context automatically so postgresql server can read/write it.
(to check the SELinux context under which postgres is running, runps xaZ | grep "postmaste[r]" | grep -o "[a-z_]*_t"
, which should print postgresql_t
. To list the context types to which postgresql_t
can write, use sesearch -s postgresql_t -A | grep ': file.*write'
. the command sesearch
belong to the setools-console
RPM package).