php mysql扩展未正确安装

问题:PHP的 MySQL 相关扩展未正确安装

此问题疑似 1Panel 的 bug

我在腾讯的大陆地区公网服务器和VMWare做了相同的尝试,均为此结果

复现:

系统:Debian 12 amd64

使用一键命令安装的1panel

1panel version: v1.10.2-lts
mode: stable

在运行环境中新增PHP运行环境,

名称我输入了 PHP82

PHP 版本我选择了 8.2.15

我尝试过的扩展源:ustc和tuna

扩展模板默认

扩展:mysqli, pdo_mysql

构建日志:build.log

#0 building with "default" instance using docker driver

#1 [1panel-php internal] load build definition from Dockerfile
#1 transferring dockerfile: 1.25kB done
#1 DONE 0.0s

#2 [1panel-php internal] load metadata for docker.io/library/php:8.2.15-fpm-alpine
#2 DONE 1.1s

#3 [1panel-php internal] load .dockerignore
#3 transferring context: 2B done
#3 DONE 0.0s

#4 [1panel-php  1/12] FROM docker.io/library/php:8.2.15-fpm-alpine@sha256:9f358983faaf1b5902ef9e6303ebc863b9be793a13e66094e366732c20fe3e7e
#4 DONE 0.0s

#5 [1panel-php internal] load build context
#5 transferring context: 5.10MB 0.0s done
#5 DONE 0.0s

#6 [1panel-php  9/12] RUN apk add gnu-libiconv libstdc++ --no-cache --repository http://mirrors.ustc.edu.cn/alpine/edge/community/ --allow-untrusted
#6 CACHED

#7 [1panel-php  3/12] ADD ./extensions/install-php-extensions  /usr/local/bin/
#7 CACHED

#8 [1panel-php  6/12] WORKDIR /tmp/extensions
#8 CACHED

#9 [1panel-php  7/12] RUN chmod +x install.sh     && sh install.sh     && rm -rf /tmp/extensions
#9 CACHED

#10 [1panel-php  2/12] RUN if [ mirrors.ustc.edu.cn ] ; then sed -i "s/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g" /etc/apk/repositories ; fi
#10 CACHED

#11 [1panel-php  8/12] RUN apk --no-cache add tzdata     && cp "/usr/share/zoneinfo/Asia/Shanghai" /etc/localtime     && echo "Asia/Shanghai" > /etc/timezone
#11 CACHED

#12 [1panel-php 11/12] RUN apk --no-cache add shadow && usermod -u 1000 www-data && groupmod -g 1000 www-data
#12 CACHED

#13 [1panel-php  5/12] COPY ./extensions /tmp/extensions
#13 CACHED

#14 [1panel-php 10/12] RUN curl -o /usr/bin/composer https://mirrors.aliyun.com/composer/composer.phar     && chmod +x /usr/bin/composer
#14 CACHED

#15 [1panel-php  4/12] RUN chmod uga+x /usr/local/bin/install-php-extensions
#15 CACHED

#16 [1panel-php 12/12] WORKDIR /www
#16 CACHED

#17 [1panel-php] exporting to image
#17 exporting layers done
#17 writing image sha256:5d7d6b237d25cbbab89ce67f190e799e001a3b83efc8b703a6d0ae8ee0dc741d done
#17 naming to docker.io/library/1panel-php:8.2.15 done
#17 DONE 0.0s

然后我选择了上面构建的运行环境新建了一个网站,参数除域名输入框外均为默认

我创建了一个test.php

内容如下:

<?php

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

// 数据库连接配置
$dbConfig = [
    'host' => 'localhost',
    'username' => 'main_site',
    'password' => 'fmtbeGnsdk66rAci',
    'database' => 'main_site'
];

// 文件操作配置
$fileConfig = [
    'filename' => 'test_iejfhruguryhirg.txt',
    'fileContent' => '测试的文件内容😊'
];

// 检测 MySQLi 扩展是否可用
if (extension_loaded('mysqli')) {
    // MySQLi 连接数据库
    $mysqli = new mysqli($dbConfig['host'], $dbConfig['username'], $dbConfig['password'], $dbConfig['database']);

    // 检查 MySQLi 连接是否成功
    if ($mysqli->connect_errno) {
        echo "Failed to connect to MySQL: " . $mysqli->connect_error;
    } else {
        echo "MySQLi connected successfully<br>";
    }

    // 关闭 MySQLi 连接
    $mysqli->close();
} else {
    echo "MySQLi extension is not available<br>";
}

echo "<br>";

// 检测 PDO 扩展是否可用
if (extension_loaded('pdo')) {
    // PDO 连接数据库
    try {
        $pdo = new PDO("mysql:host={$dbConfig['host']};dbname={$dbConfig['database']}", $dbConfig['username'], $dbConfig['password']);

        // 设置 PDO 错误模式为异常
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

        echo "PDO connected successfully<br>";
    } catch(PDOException $e) {
        echo "PDO connection failed: " . $e->getMessage();
    }
} else {
    echo "PDO extension is not available<br>";
}

echo "<br>";

// 文件读写测试
$filename = $fileConfig['filename'];
$fileContent = $fileConfig['fileContent'];

// 写入文件
if (file_put_contents($filename, $fileContent) !== false) {
    echo "成功:写入文件成功<br>";
} else {
    echo "失败:写入文件失败<br>";
}

// 读取文件
$fileData = file_get_contents($filename);
if ($fileData !== false) {
    echo "成功:读取文件内容【{$fileData}】<br>";
} else {
    echo "失败:读取文件失败<br>";
}

// 删除文件
if (unlink($filename)) {
    echo "成功:文件已删除<br>";
} else {
    echo "失败:文件删除失败<br>";
}

上述脚本我自己写的用于测试基本功能。文件测试没有问题,可以忽略。数据库连接测试存在问题

我的MySQL是从应用商店安装的8.2.0版本,已勾选端口外部访问

我也正确的在面板上创建了代码配置中的MySQL数据库和用户名,我使用Navcat工具测试了MySQL连接,连接成功,且CURD操作没有问题

我访问test.php报错

Fatal error: Uncaught mysqli_sql_exception: No such file or directory in /www/sites/my_domain/index/test.php:24 Stack trace: #0 /www/sites/my_domain/index/test.php(24): mysqli->__construct('localhost', 'main_site', Object(SensitiveParameterValue), 'main_site') #1 {main} thrown in /www/sites/my_domain/index/test.php on line 24

这说明1Panel自动配置的扩展存在问题

也就是PHP 连接不上MySQL,缺失连接驱动?

我的站点php配置如下:我没有做任何修改(由于论坛篇幅有限,我展示的删除了注释的部分)

[PHP]engine = On
short_open_tag = Off
precision = 14output_buffering = 4096

zlib.output_compression = Offimplicit_flush = Off

unserialize_callback_func =

serialize_precision = -1

disable_functions =

disable_classes =

zend.enable_gc = On

expose_php = Offmax_execution_time = 30
max_input_time = 60

memory_limit = 256M

;

;
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT

display_errors = Off

display_startup_errors = Off
log_errors = On

log_errors_max_len = 1024

ignore_repeated_errors = Offignore_repeated_source = Offreport_memleaks = Ontrack_errors = Off

html_errors = Onerror_log = /var/log/php/php.error.log

variables_order = "GPCS"
request_order = "GP"register_argc_argv = Off

auto_globals_jit = Onpost_max_size = 100M
auto_prepend_file =
auto_append_file =
;default_mimetype = "text/html"
default_charset = "UTF-8";;
doc_root =

user_dir =
enable_dl = Off
file_uploads = Onupload_max_filesize = 50Mmax_file_uploads = 20

allow_url_fopen = On
allow_url_include = Off
default_socket_timeout = 60
;

;

;

;

;

;

;

;;;

[CLI Server]

cli_server.color = On

[Date]date.timezone = Asia/Shanghai

[filter]
[iconv][intl]

[sqlite3][Pcre]
[Pdo]
[Pdo_mysql]pdo_mysql.cache_size = 2000

pdo_mysql.default_socket=

[Phar][mail function]SMTP = localhost

smtp_port = 25
mail.add_x_header = On

[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1

odbc.defaultlrl = 4096odbc.defaultbinmode = 1
[Interbase]

ibase.allow_persistent = 1ibase.max_persistent = -1ibase.max_links = -1ibase.timestampformat = "%Y-%m-%d %H:%M:%S"ibase.dateformat = "%Y-%m-%d"ibase.timeformat = "%H:%M:%S"

[MySQLi]
mysqli.max_persistent = -1

mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.cache_size = 2000
mysqli.default_port = 3306

mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =

mysqli.default_pw =mysqli.reconnect = Off

[mysqlnd]
mysqlnd.collect_statistics = On

mysqlnd.collect_memory_statistics = Off[OCI8]

[PostgreSQL]pgsql.allow_persistent = On

pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1

pgsql.ignore_notice = 0

pgsql.log_notice = 0

[bcmath]bcmath.scale = 0

[browscap]
[Session]session.save_handler = files

;

;

;;

;;

;session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = phpsession.gc_probability = 1

session.gc_divisor = 1000

session.gc_maxlifetime = 1440

session.referer_check =

session.cache_limiter = nocache
session.cache_expire = 180session.use_trans_sid = 0session.sid_length = 26session.trans_sid_tags = "a=href,area=href,frame=src,form="
session.sid_bits_per_character = 5[Assertion]
zend.assertions = -1[COM]
[mbstring][gd]
[exif][Tidy]tidy.clean_output = Off

[soap]soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"

soap.wsdl_cache_ttl=86400soap.wsdl_cache_limit = 5

[sysvshm]
[ldap]

ldap.max_links = -1

[dba][opcache]

[curl]

[openssl]
[XDebug]
xdebug.remote_enable = 1
xdebug.remote_handler = "dbgp"

xdebug.remote_host = host.docker.internal

xdebug.remote_log = /var/log/php/xdebug.log

SERVER_ENV=develop

yaf.use_spl_autoload=1

[xhprof]

猜测可能的问题原因

mysqli.default_socket =

pdo_mysql.default_socket=

均为空

而翻阅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。这么说来上面报错不存在的地址就是在源代码中给写死了,所以需要1panel设置为正确的值。

而1panel并未设置为正确的值导致连接失败

由于我的能力和精力有限,还要忙工作,我旧先把问题丢到贵站论坛了,有望大佬解决

补充:访问默认的index.php的结果

## 版本信息

* PHP版本:8.2.15

## 已安装扩展

1. Core=8.2.15
2. date=8.2.15
3. libxml=8.2.15
4. openssl=8.2.15
5. pcre=8.2.15
6. sqlite3=8.2.15
7. zlib=8.2.15
8. ctype=8.2.15
9. curl=8.2.15
10. dom=20031129
11. fileinfo=8.2.15
12. filter=8.2.15
13. hash=8.2.15
14. iconv=8.2.15
15. json=8.2.15
16. mbstring=8.2.15
17. SPL=8.2.15
18. session=8.2.15
19. PDO=8.2.15
20. pdo_sqlite=8.2.15
21. standard=8.2.15
22. posix=8.2.15
23. random=8.2.15
24. readline=8.2.15
25. Reflection=8.2.15
26. Phar=8.2.15
27. SimpleXML=8.2.15
28. tokenizer=8.2.15
29. xml=8.2.15
30. xmlreader=8.2.15
31. xmlwriter=8.2.15
32. mysqlnd=mysqlnd 8.2.15
33. cgi-fcgi=8.2.15
34. mysqli=8.2.15
35. pdo_mysql=8.2.15
36. sodium=8.2.15

使用phpmyadmin登录也是报错mysqli::real_connect(): (HY000/2002): No such file or directory

难不成我只能传统的用内网
172.18.0.1或
172.17.0.1连接吗
想要方便的sock