You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP用MySQLi/PDO连远程MySQL报权限拒绝,CLI连接正常求原因

排查PHP连接远程MySQL报Permission denied的问题

这种情况我之前碰到过好几次,核心原因基本都是Web服务器进程的权限限制和命令行用户不一样导致的——毕竟你用命令行是自己的用户身份,而PHP是跑在Apache/Nginx的进程下(比如www-data、apache用户),咱们一步步来排查:

1. 优先检查SELinux(最常见的元凶)

很多Linux发行版默认开启SELinux,它会严格限制进程的网络访问权限,哪怕你数据库权限开对了,Web进程也会被拦下来:

  • 先临时关闭SELinux测试:sudo setenforce 0,然后再试PHP连接,如果能成功,那就是SELinux的问题。
  • 永久解决的话,给Web进程授权访问远程数据库:
    • 如果用的是默认3306端口,执行:sudo semanage port -a -t mysqld_port_t -p tcp 3306
    • 或者直接允许HTTP进程连接数据库:setsebool -P httpd_can_network_connect_db 1

2. 检查AppArmor限制(部分Debian/Ubuntu系统)

如果是Debian或Ubuntu系服务器,可能用了AppArmor来限制进程权限:

  • 查看AppArmor状态:sudo aa-status,看有没有针对Apache/Nginx的规则。
  • 如果有,编辑对应的配置文件(比如/etc/apparmor.d/usr.sbin.apache2),添加允许访问远程MySQL端口的规则,然后重新加载AppArmor:sudo systemctl reload apparmor

3. 确认防火墙/iptables的进程级规则

虽然命令行能连,但有些服务器会针对特定用户/进程设置出站规则:

  • 检查iptables规则:sudo iptables -L -n -v,看有没有拒绝www-data或apache用户访问3306端口的规则。
  • 如果有,添加允许规则:sudo iptables -A OUTPUT -m owner --uid-owner www-data -p tcp --dport 3306 -j ACCEPT

4. 核对PHP连接参数的一致性

虽然你说凭据相同,但还是要确认PHP代码里的连接参数和命令行完全一致:

  • 比如命令行用的是mysql -h remote_host_ip -u your_user -p,那PHP里的主机必须是同一个IP/域名,不能写成localhost(localhost会走socket连接,不是TCP远程连接)。
  • 举个例子,MySQLi的正确连接写法:mysqli_connect('remote_host_ip', 'your_user', 'your_pass', 'your_db', 3306);
  • PDO的写法:new PDO('mysql:host=remote_host_ip;port=3306;dbname=your_db', 'your_user', 'your_pass');

5. 排除PHP配置的特殊限制

  • 检查php.ini里的open_basedir配置:虽然这个主要限制文件系统访问,但极少数情况下错误的配置可能间接影响网络,要是设置了这个参数,确保没有过度限制。
  • 查看mysqlnd相关配置:比如mysqlnd.net_read_timeout、mysqlnd.net_write_timeout,不过这些一般导致超时错误,不是Permission denied,但可以确认没有奇怪的数值。

总结

最大概率是SELinux或AppArmor的安全上下文限制,因为Web进程的身份和你命令行用户的身份权限隔离了,只要给Web进程授权远程数据库访问权限,问题基本就能解决。

内容的提问来源于stack exchange,提问作者Mr J

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:33:13