Tag Archives: php mysqli

Remember to check the error of no such file or directory in PHP mysqli once

Geeks, please accept the hero post of 2021 Microsoft x Intel hacking contest>>>

Recently, one of the company’s development machines broke down and needed to transfer some work-related systems to another machine. In the process of transferring mantis, it was found that MySQL could not be connected, and the error was no such file or directory. This error message obviously told me that the file did not exist, but I connected to MySQL through the network. Why did I prompt that the file did not exist?So I wrote a test code

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

Sure enough, it’s still wrong

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

In order to ensure that the parameters are correct, the MySQL client is used for testing

mysql -uroot -hlocalhost

Well, it’s connected. There’s no error at all. That means there’s no problem with the parameters. But why can’t MySQL client connect normally with the same parameters and PHP connect?In order to find out, I ran this code again with strace, and found that the system call connect is not TCP, but UNIX domain, and the file path is/TMP/mysql.sock, but this file does not exist

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

So far, I have known the source of the error. It is the use of unixdomain to connect to an address that does not exist, resulting in an error. But why use unixdomain to connect to MySQL?And where does this address come from?According to historical records, when you use localhost to connect, you will use unixdomain. So MySQL client also uses unixdomain?So we used strace to MySQL again

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

Found that connect does use unixdomain, but… This file path is completely different from the above, and this path exists.. But where did/TMP/mysql.sock come from?So I kept going through the PHP document, which clearly pointed out that the socket parameter of mysqli constructor (that is, the file path of the UNIX domain mentioned above) is from mysqli. Default of php.ini by default_ Then check the parameters again

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

Huh?It’s not worth it. Where did this product come from?In order to find out the truth, I began to look through the source code of mysqli. Sure enough, I found such a paragraph from the source code

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;
}

If you use localhost, use unixdomain. The file path is the socket in the parameter. If the parameter is empty, then write/TMP/mysql.socket. In this way, the above error address is dead in the source code, so you need to manually set it to the correct value. So modify the parameters of mysqli and test again

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

Sure enough, we have found out the truth. We can’t connect because we use localhost and mysqli. Default_ The value of socket is empty, and the default path provided in the source code does not exist. I don’t have to ask here. Can I add two judgments?If you use localhost and socket is not empty, you can use unixdomain instead of providing the default path, because if you install PHP first and then mysql, the default_ Socket will be null

Of course, it’s very simple to solve this problem. There are many articles on the Internet about how to solve it, such as mysqli. Default_ Change the value of socket to the correct path, or change localhost to 127.0.0.1, etc. Mainly want to know why do not configure socket will be wrong, to find the root of the problem to suit the remedy