起因
在某云买了个新的VPS,接下来自然是把之前的网站搬上去了。之前我是用lnmp脚本安装的环境。这一次我要自己安装!
一顿操作之后,Nginx+MariaDB+PHP安装好了!既然换了新机器,肯定软件都要安装新的啦。于是:
- PHP 7.3.17 -> 7.4.10
- Nginx 1.12.2 -> 1.18.0
- MariaDB 10.1.19 -> 10.5.5
一顿操作完安装好后,自然是开始配置了
改密码
第一件事自然是给MariaDB改个密码了。轻车熟路的,先用skip-grant-tables模式启动,然后开始噼里啪啦的敲SQL:
MariaDB [(none)]> use mysql Database changed MariaDB [mysql]> UPDATE user SET Password=password('123') WHERE User='root' AND Host='localhost' ERROR 1356 (HY000): View 'mysql.user' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
哎?怎么修改不了?仔细一琢磨,原来mysql.user是个View。那就换成其他方式吧。说实话用SET也挺好
MariaDB [mysql]> SET Password FOR root@localhost = password('123'); MariaDB [mysql]> FLUSH PRIVILEGES;
连接
接下来当然是导入之前的数据了,打开phpMyAdmin,密码已经被KeePass自动填充上了。点击登录。哎?怎么报错mysqli_real_connect(): (HY000/2002): No such file or directory
了?
网上搜索了一下,有人说把地址改一下就行了。于是在config.inc.php里面把localhost改成了127.0.0.1,然后继续重试。倒是不提示No such file了,变成一个更奇怪的提示:
Packets out of order. Expected 0 received 1. Packet size=68 mysqli::real_connect(): Error while reading greeting packet. PID=10000 mysqli::real_connect(): MySQL server has gone away
看上去没有任何头绪。一开始以为是驱动版本不兼容,换了Navicat尝试还是不行。后来尝试新建了一个用于127.0.0.1的用户,然后刷新权限重启MariaDB才连接成功。
Systemd?
连接成功,导入数据,上传程序,一气呵成。接下来一运行,又遇到了“No such file or directory”的错误提示。嗯?那看来得解决解决。
查了一堆资料,了解到localhost会在内部当做Unix socket连接方式处理。问题不外乎有几个:
- sock位置不对
- 没有权限
把phpinfo打印出来,发现路径是/tmp/mysql.sock
,没有问题。再到tmp目录下ls看了看:
[root@shuangya web]# ls -l /tmp total 276 srwxrwxrwx 1 mysql mysql 0 Sep 26 22:44 mysql.sock
看上去也没有问题呀?写一个测试脚本试试:
<?php $host = "localhost"; $username = "root"; $password = "*******"; $dbname = "mysql"; $charset = "utf8"; $dsn = "mysql:dbname=$dbname;port=3306;host=$host"; try{ $pdo = new Pdo($dsn, $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(PDOException $e){ die("连接失败: ".$e->getMessage()); } var_dump($pdo->query('SELECT * FROM user')); echo "ok";
运行一看,完全正常……
难道是用户问题?于是把www用户打开,切换过去运行,发现也完全正常。
怎么回事?试试手动读取一下tmp目录,要是能读出来的话,那就可以排除掉权限问题了。
<?php $dh = opendir('/tmp'); while ($d = readdir($dh)) { var_dump($d); } closedir($dh);
出乎人意料的结果:
. .. sess_1716b75d954b27ba1e53b088d1c23809
哎?居然没有mysql.sock?但是我在tmp目录下面也没有看到这个“sess_”的文件呀?全盘搜索了一下,结果发现它位于systemd-private-xxxxxxxxxxxxx
下面。
看这个名字就猜到了,它一定和systemd有点什么关系。打开php-fpm.service
一看:
[Unit] Description=The PHP FastCGI Process Manager After=syslog.target network.target [Service] Type=forking PIDFile=/var/run/php-fpm.pid ExecStart=/usr/local/php/sbin/php-fpm ExecReload=/bin/kill -USR2 $MAINPID PrivateTmp=true
那看来这个PrivateTmp=true
应该就是罪魁祸首了。搜索了一下,这个选项会让启动的服务有一个私有的tmp目录。怪不得php找不到mysql的sock文件……
解决方法就更简单了,把它关掉,万事大吉~