博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
记一次php mysqli出现No such file or directory的错误排查
阅读量:6657 次
发布时间:2019-06-25

本文共 2284 字,大约阅读时间需要 7 分钟。

  hot3.png

最近公司的一台开发机器坏了,需要把部分工作相关的系统转移到另一台机器上,在转移mantis的过程中发现mysql连不上了,而且错误居然是No such file or directory,这个错误信息很明显告诉我文件不存在,但是我是通过网络连mysql,何故会提示文件不存在?于是写了一段测试代码。

$mysqli = new mysqli('localhost', 'root', '', 'bugtracker');if ($mysqli->connect_error) {    die('Connect Error (' . $mysqli->connect_errno . '): '. $mysqli->connect_error);}

果然,还是报错!!!!

PHP Warning:  mysqli::mysqli(): (HY000/2002): No such file or directory in /root/test.php on line 2

为了确保参数没错,使用mysql客户端进行测试

mysql -uroot -hlocalhost

嗯,连上了,完全没有任何错误,那说明参数是没有问题的,可为什么相同的参数,mysql客户端连接正常,php连接不上?为了一探究竟,于是使用strace再次跑了一下这段代码,发现系统调用的connect居然不是使用tcp,而是unixdomain,文件路径是/tmp/mysql.sock,而这个文件确实不存在

connect(3, {sa_family=AF_FILE, path="/tmp/mysql.sock"}, 17) = -1 ENOENT (No such file or directory)

到这里,我已经知道错误的来源,是使用unixdomain去连接了一个不存的地址,导致报错,可为什么会使用unixdomain连接mysql呢?而这个地址又从哪里来的呢?于是又查阅了相关资(Bai)料(Du),根据史书记载,当使用localhost进行连接的时候,会使用unixdomain的方式,那这么说来mysql客户端也是使用unixdomain了?于是又对mysql使用了一次strace

connect(3, {sa_family=AF_FILE, path="/var/lib/mysql/mysql.sock"}, 110) = 0

发现connect确实是使用unixdomain,但是.......这个文件路径跟上面的完全不一样,而这个路径是存在的。。可上面/tmp/mysql.sock到底哪里来的?于是又马不停蹄的去翻阅php文档,文档明确指出,mysqli的构造函数socket参数(也就是上面提到的unixdomain的文件路径)默认从php.ini的mysqli.default_socket中取,那么再次检查参数

php -i|grep 'mysqli.default_socket'mysqli.default_socket => no value => no value

嗯哼?没有值,闹呢这是。那这个货到底从哪里来的,为了探明事情真相,开始翻阅mysqli的源代码,果然,从源代码中找出了这么一段

if (host_len == sizeof("localhost") - 1 && !strncasecmp(host, "localhost", host_len)) {    DBG_INF_FMT("socket=%s", socket_or_pipe? socket_or_pipe:"n/a");    if (!socket_or_pipe) {        socket_or_pipe = "/tmp/mysql.sock";    }    transport_len = mnd_sprintf(&transport, 0, "unix://%s", socket_or_pipe);    unix_socket = TRUE;}

如果使用localhost,就使用unixdomain,文件路径就是参数中的socket,但如果这个参数是空,那么奏写死/tmp/mysql.sock。这么说来上面报错不存在的地址就是在源代码中给写死了,所以需要自己手动设置为正确的值。于是修改mysqli的参数再次测试。

$mysqli = new mysqli('localhost', 'root', '', 'bugtracker', 3306, "/var/lib/mysql/mysql.sock");

果然好了,到这里,已经查明事情真相,连接不上就是因为使用了localhost并且mysqli.default_socket的值为空,而源码中提供的默认路径又不存在。到这里我不经要问,可否加两个判断呢?使用localhost并且socket不为空才使用unixdomain,而不提供默认路径,因为如果先装php后装mysql,那么这个default_socket就会是个空值。

当然解决这个问题其实很简单,网上有非常多的文章都有写如何解决,比如将mysqli.default_socket的值改为正确的路径,或者将localhost改成127.0.0.1等。主要还是想知道为什么不配置socket会出现错误,要找到问题的根源才好对症下药。

 

 

转载于:https://my.oschina.net/scgywx/blog/1545301

你可能感兴趣的文章
51nod1355 斐波那契的最小公倍数
查看>>
谷歌面试题求解.
查看>>
20135337——信息安全设计基础第八周学习笔记
查看>>
WordPress教程
查看>>
drf 多表
查看>>
损失函数
查看>>
对spring的理解是什么?
查看>>
Linux -- Ubuntu搭建java开发环境
查看>>
foreach和map
查看>>
angularjs封装bootstrap官网的时间插件datetimepicker
查看>>
java简单实现搜索指定后缀文件
查看>>
1738 - TWO NODES
查看>>
2019年华南理工校赛(春季赛)--I--炒股(简单思维水题)
查看>>
夜间模式的开启与关闭,父模板的制作
查看>>
Introductory Papers / Reference
查看>>
第一次,触碰Web App项目,栽过的那些坑。
查看>>
CentOS的新变化
查看>>
2013应届毕业生“大唐电信”校招应聘总结
查看>>
mysql 视图,触发器,存储
查看>>
SSE(Server-sent events)技术在web端消息推送和实时聊天中的使用
查看>>