无法连接到PostgreSQL unix域套接字

我试图从PHP Web应用程序连接到PostgreSQL Unix域套接字。 相关系统组件:

  • CentOS 7 x64(强制执行SELinux)
  • postgresql93 9.3.5-2PGDG.rhel7
  • nginx 1.6.2-1.el7.ngx
  • php-common 5.4.16-23.el7_0.3
  • php-fpm 5.4.16-23.el7_0.3
  • php-pdo 5.4.16-23.el7_0.3
  • php-pgsql 5.4.16-23.el7_0.3

PostgreSQL正在监听标准端口5432,我没有问题通过TCP / IP在127.0.0.1:5432,但是当我尝试连接到它的Unix域套接字,我有一个以下错误:

Cannot connect to database: SQLSTATE[08006] [7] could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/tmp/.s.PGSQL.5432"? 

文件/tmp/.s.PGSQL.5432存在,我可以连接使用psql

 $ psql -Uusername db_name psql (9.3.5) Type "help" for help. db_name=> 

所以PostgreSQL方面应该没有问题。 或者在那里?

来自/var/lib/pgsql/9.3/data/pg_hba.conf的相关行:

 local all username trust 

/var/lib/pgsql/9.3/data/postgresql.conf中更改Unix域套接字文件的位置并没有帮助:

 unix_socket_directories = '/var/run/pgsql' 

/var/log/audit/audit.log中没有任何内容,但我试图禁用SELinux,只是为了确保:

 # setenforce 0 

这没有帮助,所以它不是SELinux。

来自php-fpm strace的相关行:

 [pid 882] socket(PF_LOCAL, SOCK_STREAM, 0) = 5 [pid 882] fcntl(5, F_SETFL, O_RDONLY|O_NONBLOCK) = 0 [pid 882] fcntl(5, F_SETFD, FD_CLOEXEC) = 0 [pid 882] connect(5, {sa_family=AF_LOCAL, sun_path="/tmp/.s.PGSQL.5432"}, 110) = -1 ENOENT (No such file or directory) [pid 882] close(5) = 0 

文件名是正确的,再次,文件/tmp/.s.PGSQL.5432存在:

 $ ls -l /tmp/.s.PGSQL.5432 srwxrwxrwx. 1 postgres postgres 0 Nov 1 09:47 /tmp/.s.PGSQL.5432 

它看起来像php-fpm过程不chroot'ed:

 # ls -l /proc/882/root lrwxrwxrwx. 1 apache apache 0 Oct 31 19:54 /proc/882/root -> / 

在这一点上,我没有更多的想法,问题可以在这里,我将不胜感激任何帮助。

我已经解决了这个问题。 最初的原因是在php-fpm /usr/lib/systemd/system/php-fpm.service的 systemd服务文件中:

 [Service] PrivateTmp=true 

这意味着php-fpm无法看到/tmp/.s.PGSQL.5432,也没有其他位于/ tmp的东西 。 为了解决这个问题,我使用以下步骤更改了PostgreSQL Unix域套接字文件的位置:

  • 创build一个新的目录/ var / pgsql (注意改变SELinux文件的上下文):

     # mkdir /var/pgsql # chown posgres:postgres /var/pgsql # chmod 0755 /var/pgsql # semanage fcontext -a -t httpd_var_run_t "/var/pgsql(/.*)?" # restorecon -R /var/pgsql 
  • 取消注释并修改/var/lib/pgsql/9.3/data/postgresql.conf中的 unix_socket_directories参数( / tmp仍然不需要中断psql和其他程序):

     unix_socket_directories = '/tmp,/var/pgsql' 

而这里又是一个棘手的部分…在原来的文章中,我写道,我试图改变Unix域套接字文件的位置,我真的这样做。 我错过了改变的错误信息。 我以为这个错误是一样的,但事实并非如此:

 Error (256): Cannot connect to database: SQLSTATE[08006] [7] could not connect to server: Permission denied Is the server running locally and accepting connections on Unix domain socket "/var/pgsql/.s.PGSQL.5432"? 

权限被拒绝 – 这是一个可以战斗的东西。

一切正常

 # setenforce 0 

问题是:

 # audit2allow -a #============= httpd_t ============== allow httpd_t initrc_t:unix_stream_socket connectto; 

它可以被修复:

 # audit2allow -a -M httpd_postgresql_unix_socket_connect # semodule -i httpd_postgresql_unix_socket_connect.pp 

httpd_postgresql_unix_socket_connect.te的内容:

 module httpd_postgresql_unix_socket_connect 1.0; require { type httpd_t; type initrc_t; class unix_stream_socket connectto; } #============= httpd_t ============== allow httpd_t initrc_t:unix_stream_socket connectto; 

重启SELinux:

 # setenforce 1 

一切正常!

PS我很高兴知道是否有办法通过更改一些文件上下文或布尔值来避免自定义SELinux模块。 可能是这样的,因为SELinux允许nginx使用php-fpm Unix域套接字( /var/run/php5-fpm.sock ),但由于某些原因阻塞了PostgreSQL Unix域套接字的使用( /var/pgsql/.s .PGSQL.5432 )。