PHP信创= 国产Linux发行版PHP运行依赖库兼容适配方案
·
国产 Linux 发行版 PHP 运行依赖库兼容适配方案
先搞清楚问题在哪
PHP 不是一个独立程序,它运行时依赖一堆系统库(.so 文件)。国产 Linux 的问题集中在三点:
问题1:库版本太旧 → 系统自带 OpenSSL 1.0,PHP 要 1.1+
问题2:库版本太新 → 系统用 OpenSSL 3.x,老 PHP 不认识
问题3:库根本没有 → oniguruma、libzip 等在某些发行版仓库里没有
---
主流国产发行版速查表
┌───────────────────────┬──────────┬───────────┬────────────────────────────┬────────────────────┐
│ 发行版 │ 包管理器 │ 底层基础 │ 架构支持 │ 主要问题 │
├───────────────────────┼──────────┼───────────┼────────────────────────────┼────────────────────┤
│ OpenEuler 22.03/24.03 │ dnf/yum │ RHEL 系 │ x86/ARM64/LoongArch/RISC-V │ oniguruma 包名差异 │
├───────────────────────┼──────────┼───────────┼────────────────────────────┼────────────────────┤
│ 银河麒麟 V10 │ dnf/yum │ RHEL 系 │ x86/ARM64/LoongArch │ OpenSSL 版本冲突 │
├───────────────────────┼──────────┼───────────┼────────────────────────────┼────────────────────┤
│ 统信 UOS 20 │ apt │ Debian 系 │ x86/ARM64 │ libzip 版本低 │
├───────────────────────┼──────────┼───────────┼────────────────────────────┼────────────────────┤
│ 中标麒麟 7 │ yum │ RHEL 7 系 │ x86/ARM64 │ 库版本极旧 │
├───────────────────────┼──────────┼───────────┼────────────────────────────┼────────────────────┤
│ Deepin 23 │ apt │ Debian 系 │ x86/ARM64/LoongArch │ 兼容性最好 │
├───────────────────────┼──────────┼───────────┼────────────────────────────┼────────────────────┤
│ 龙蜥 AnolisOS 8 │ dnf │ RHEL 系 │ x86/ARM64 │ 接近 CentOS 8 │
└───────────────────────┴──────────┴───────────┴────────────────────────────┴────────────────────┘
---
第一步:诊断脚本(先跑这个,搞清楚你的环境)
#!/bin/bash
# diagnose.sh - 一键诊断 PHP 依赖库状态
echo "========================================"
echo " 国产Linux PHP依赖库诊断报告"
echo "========================================"
# 1. 系统信息
echo ""
echo "【系统信息】"
cat /etc/os-release | grep -E "^(NAME|VERSION|ID)="
echo "架构: $(uname -m)"
echo "内核: $(uname -r)"
# 2. 包管理器类型
echo ""
echo "【包管理器】"
if command -v dnf &>/dev/null; then
echo "类型: dnf (RHEL系)"
PKG_MGR="dnf"
elif command -v yum &>/dev/null; then
echo "类型: yum (RHEL系)"
PKG_MGR="yum"
elif command -v apt &>/dev/null; then
echo "类型: apt (Debian系)"
PKG_MGR="apt"
fi
# 3. 检查关键库
echo ""
echo "【关键依赖库检查】"
check_lib() {
local libname=$1
local result=$(ldconfig -p 2>/dev/null | grep "$libname" | head -3)
if [ -n "$result" ]; then
echo " ✓ $libname 已安装:"
echo "$result" | awk '{print " " $0}'
else
echo " ✗ $libname 未找到"
fi
}
check_lib "libssl"
check_lib "libcrypto"
check_lib "libcurl"
check_lib "libxml2"
check_lib "libonig" # oniguruma,mbstring 需要
check_lib "libzip"
check_lib "libz" # zlib
check_lib "libsqlite3"
check_lib "libpng"
check_lib "libjpeg"
check_lib "libfreetype"
check_lib "libreadline"
check_lib "libbz2"
check_lib "libgmp"
check_lib "libsodium" # PHP 7.2+ 内置 sodium 需要
# 4. 检查编译工具
echo ""
echo "【编译工具链】"
for tool in gcc g++ make cmake autoconf phpize; do
if command -v $tool &>/dev/null; then
echo " ✓ $tool: $(${tool} --version 2>&1 | head -1)"
else
echo " ✗ $tool: 未安装"
fi
done
# 5. OpenSSL 版本详情(最容易出问题)
echo ""
echo "【OpenSSL 详情】"
openssl version -a 2>/dev/null || echo " openssl 命令未找到"
echo " 头文件位置:"
find /usr/include -name "ssl.h" 2>/dev/null | head -3
# 6. 如果 PHP 已安装,检查扩展
echo ""
echo "【PHP 现状】"
if command -v php &>/dev/null; then
echo " PHP版本: $(php -v | head -1)"
echo " 缺失扩展:"
for ext in openssl curl mbstring zip pdo_mysql redis swoole; do
php -m 2>/dev/null | grep -q "^${ext}$" || echo " ✗ $ext"
done
else
echo " PHP 未安装"
fi
echo ""
echo "========================================"
echo "诊断完成,根据上面结果对照下方方案处理"
echo "========================================"
chmod +x diagnose.sh && bash diagnose.sh
---
第二步:按发行版安装依赖
方案A:RHEL 系(OpenEuler / 银河麒麟 / 龙蜥)
#!/bin/bash
# install_deps_rhel.sh
set -e
echo "=== 安装基础编译工具 ==="
dnf groupinstall -y "Development Tools"
dnf install -y \
gcc gcc-c++ make cmake \
autoconf automake libtool \
pkg-config bison re2c
echo "=== 安装 PHP 核心依赖 ==="
dnf install -y \
openssl-devel \
libcurl-devel \
libxml2-devel \
zlib-devel \
bzip2-devel \
readline-devel \
sqlite-devel \
libsodium-devel \
gmp-devel \
libffi-devel
echo "=== 安装 oniguruma(mbstring 必须)==="
# OpenEuler/麒麟 包名可能不同,逐个尝试
if dnf list oniguruma-devel &>/dev/null 2>&1; then
dnf install -y oniguruma-devel
elif dnf list onig-devel &>/dev/null 2>&1; then
dnf install -y onig-devel
else
echo "仓库里没有 oniguruma,从源码编译..."
cd /usr/local/src
wget https://github.com/kkos/oniguruma/releases/download/v6.9.9/onig-6.9.9.tar.gz
tar -xzf onig-6.9.9.tar.gz && cd onig-6.9.9
./configure --prefix=/usr/local
make -j$(nproc) && make install
ldconfig # 刷新动态库缓存
fi
echo "=== 安装 libzip ==="
# 检查版本,PHP 7.4+ 需要 libzip >= 1.2.0
LIBZIP_VER=$(dnf info libzip-devel 2>/dev/null | grep Version | awk '{print $3}')
echo "仓库 libzip 版本: $LIBZIP_VER"
if dnf install -y libzip-devel 2>/dev/null; then
echo "libzip-devel 安装成功"
else
echo "从源码编译 libzip..."
cd /usr/local/src
wget https://libzip.org/download/libzip-1.10.1.tar.gz
tar -xzf libzip-1.10.1.tar.gz && cd libzip-1.10.1
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local
make -j$(nproc) && make install
ldconfig
fi
echo "=== 安装图像处理库 ==="
dnf install -y \
libpng-devel \
libjpeg-turbo-devel \
freetype-devel \
libwebp-devel \
libavif-devel 2>/dev/null || true # avif 可能没有,忽略错误
echo "=== 安装数据库客户端库 ==="
dnf install -y \
mysql-devel \
postgresql-devel 2>/dev/null || \
dnf install -y \
mariadb-devel \
postgresql-devel 2>/dev/null || true
echo "=== 刷新动态库缓存 ==="
ldconfig
echo "依赖安装完成!"
方案B:Debian 系(统信 UOS / Deepin)
#!/bin/bash
# install_deps_debian.sh
set -e
echo "=== 更新软件源 ==="
apt update
echo "=== 安装编译工具 ==="
apt install -y \
build-essential \
gcc g++ make cmake \
autoconf automake libtool \
pkg-config bison re2c
echo "=== 安装 PHP 核心依赖 ==="
apt install -y \
libssl-dev \
libcurl4-openssl-dev \
libxml2-dev \
zlib1g-dev \
libbz2-dev \
libreadline-dev \
libsqlite3-dev \
libsodium-dev \
libgmp-dev \
libffi-dev \
libonig-dev \
libzip-dev
echo "=== 安装图像处理库 ==="
apt install -y \
libpng-dev \
libjpeg-dev \
libfreetype6-dev \
libwebp-dev
echo "=== 安装数据库客户端库 ==="
apt install -y \
libmysqlclient-dev \
libpq-dev 2>/dev/null || \
apt install -y \
default-libmysqlclient-dev \
libpq-dev
ldconfig
echo "依赖安装完成!"
---
第三步:处理 OpenSSL 版本冲突(最常见问题)
问题场景说明
银河麒麟 V10 ARM:系统自带 OpenSSL 1.1.1,但某些版本 curl 链接的是 OpenSSL 3.x
→ PHP 编译时 libcurl 和 openssl 版本不匹配,运行时报错
中标麒麟 7:系统自带 OpenSSL 1.0.2,PHP 8.x 要求 OpenSSL >= 1.1.0
→ 必须手动升级 OpenSSL
解决方案:编译安装指定版本 OpenSSL
#!/bin/bash
# install_openssl.sh - 编译安装 OpenSSL 1.1.1,不替换系统版本
OPENSSL_VERSION="1.1.1w" # 最后一个 1.1.1 LTS 版本
INSTALL_DIR="/usr/local/openssl-1.1.1"
cd /usr/local/src
wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz
tar -xzf openssl-${OPENSSL_VERSION}.tar.gz
cd openssl-${OPENSSL_VERSION}
# 根据架构选择编译目标
ARCH=$(uname -m)
case $ARCH in
x86_64)
TARGET="linux-x86_64"
;;
aarch64)
TARGET="linux-aarch64"
;;
loongarch64)
TARGET="linux-generic64" # LoongArch 用通用目标
;;
*)
TARGET="linux-generic64"
;;
esac
echo "架构: $ARCH,编译目标: $TARGET"
./Configure \
$TARGET \
--prefix=$INSTALL_DIR \
--openssldir=$INSTALL_DIR/ssl \
shared \
zlib \
no-ssl3 \
no-weak-ssl-ciphers
make -j$(nproc)
make install
# 不覆盖系统 OpenSSL,只是让 PHP 编译时能找到这个版本
echo "OpenSSL $OPENSSL_VERSION 安装到 $INSTALL_DIR"
echo "PHP 编译时加参数: --with-openssl=$INSTALL_DIR"
PHP 编译时指定 OpenSSL 路径
# 编译 PHP 时,明确告诉它用哪个 OpenSSL
./configure \
--prefix=/usr/local/php \
--with-openssl=/usr/local/openssl-1.1.1 \
--with-curl \
# ... 其他参数
---
第四步:处理 libcurl 与 OpenSSL 后端不匹配
这是银河麒麟 V10 的高频问题:系统 curl 编译时用的 OpenSSL,但运行时找到的是 NSS 或 GnuTLS。
# 诊断:看 curl 链接的是哪个 SSL 后端
curl-config --ssl-backends 2>/dev/null || \
curl --version | grep -i ssl
# 如果输出是 NSS 或 GnuTLS,但你的 PHP 用 OpenSSL,就会冲突
# 解决:重新编译 curl,强制用 OpenSSL
#!/bin/bash
# install_curl_openssl.sh - 编译 curl,强制链接 OpenSSL
CURL_VERSION="8.7.1"
OPENSSL_DIR="/usr/local/openssl-1.1.1" # 上一步装的
cd /usr/local/src
wget https://curl.se/download/curl-${CURL_VERSION}.tar.gz
tar -xzf curl-${CURL_VERSION}.tar.gz
cd curl-${CURL_VERSION}
./configure \
--prefix=/usr/local/curl \
--with-openssl=$OPENSSL_DIR \
--with-zlib \
--enable-http \
--enable-ftp \
--enable-file \
--enable-proxy \
--enable-ipv6 \
--disable-ldap \
--without-nss \
--without-gnutls
make -j$(nproc)
make install
echo "curl 安装完成,SSL 后端: $(curl --version | grep SSL)"
# PHP 编译时指定用这个 curl
./configure \
--with-curl=/usr/local/curl \
# ...
---
第五步:统一的 PHP 编译脚本(适配所有国产发行版)
#!/bin/bash
# build_php.sh - 国产Linux通用PHP编译脚本
set -e
PHP_VERSION="8.2.18"
PHP_INSTALL_DIR="/usr/local/php"
# 自动检测并设置依赖路径
OPENSSL_DIR=""
CURL_DIR=""
LIBZIP_DIR=""
# 检查是否有自编译的版本
[ -d "/usr/local/openssl-1.1.1" ] && OPENSSL_DIR="/usr/local/openssl-1.1.1"
[ -d "/usr/local/curl" ] && CURL_DIR="/usr/local/curl"
[ -d "/usr/local/libzip" ] && LIBZIP_DIR="/usr/local/libzip"
# 构建 configure 参数
CONFIGURE_ARGS=(
"--prefix=$PHP_INSTALL_DIR"
"--with-config-file-path=$PHP_INSTALL_DIR/etc"
"--with-config-file-scan-dir=$PHP_INSTALL_DIR/etc/conf.d"
"--enable-fpm"
"--enable-cli"
"--enable-opcache"
"--enable-sockets"
"--enable-pcntl"
"--enable-mbstring"
"--enable-bcmath"
"--enable-intl"
"--enable-calendar"
"--enable-exif"
"--enable-ftp"
"--with-zlib"
"--with-bz2"
"--with-readline"
"--with-gmp"
"--with-sodium"
"--with-pdo-mysql"
"--with-mysqli"
"--with-pdo-pgsql"
"--with-pgsql"
"--with-pdo-sqlite"
"--with-sqlite3"
)
# 动态添加有自编译版本的参数
if [ -n "$OPENSSL_DIR" ]; then
CONFIGURE_ARGS+=("--with-openssl=$OPENSSL_DIR")
echo "使用自编译 OpenSSL: $OPENSSL_DIR"
else
CONFIGURE_ARGS+=("--with-openssl")
echo "使用系统 OpenSSL"
fi
if [ -n "$CURL_DIR" ]; then
CONFIGURE_ARGS+=("--with-curl=$CURL_DIR")
echo "使用自编译 curl: $CURL_DIR"
else
CONFIGURE_ARGS+=("--with-curl")
fi
if [ -n "$LIBZIP_DIR" ]; then
CONFIGURE_ARGS+=("--with-zip=$LIBZIP_DIR")
else
CONFIGURE_ARGS+=("--with-zip")
fi
# 图像库(可选,失败不中断)
CONFIGURE_ARGS+=(
"--enable-gd"
"--with-freetype"
"--with-jpeg"
"--with-webp"
)
# 下载源码
cd /usr/local/src
if [ ! -f "php-${PHP_VERSION}.tar.gz" ]; then
wget "https://www.php.net/distributions/php-${PHP_VERSION}.tar.gz"
fi
tar -xzf php-${PHP_VERSION}.tar.gz
cd php-${PHP_VERSION}
echo "=== 开始配置 ==="
echo "参数: ${CONFIGURE_ARGS[@]}"
# 设置 PKG_CONFIG_PATH,让 configure 能找到自编译的库
export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:/usr/local/openssl-1.1.1/lib/pkgconfig:/usr/local/curl/lib/pkgconfig:
$PKG_CONFIG_PATH"
export LD_LIBRARY_PATH="/usr/local/lib:/usr/local/openssl-1.1.1/lib:/usr/local/curl/lib:$LD_LIBRARY_PATH"
./configure "${CONFIGURE_ARGS[@]}"
echo "=== 开始编译(使用 $(nproc) 个核心)==="
make -j$(nproc)
echo "=== 安装 ==="
make install
# 创建配置
mkdir -p $PHP_INSTALL_DIR/etc/conf.d
cp php.ini-production $PHP_INSTALL_DIR/etc/php.ini
# 写入 PATH
cat > /etc/profile.d/php.sh << EOF
export PATH=$PHP_INSTALL_DIR/bin:\$PATH
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/openssl-1.1.1/lib:\$LD_LIBRARY_PATH
EOF
source /etc/profile.d/php.sh
echo "=== PHP 安装完成 ==="
php -v
---
第六步:运行时动态库找不到的问题
编译成功了,但运行时报 error while loading shared libraries,这是因为自编译的库不在系统默认搜索路径里。
# 方法1:写入 ldconfig 配置(推荐,永久生效)
cat > /etc/ld.so.conf.d/local-libs.conf << 'EOF'
/usr/local/lib
/usr/local/lib64
/usr/local/openssl-1.1.1/lib
/usr/local/curl/lib
/usr/local/libzip/lib
EOF
# 刷新缓存
ldconfig
# 验证
ldconfig -p | grep libssl
ldconfig -p | grep libcurl
# 方法2:环境变量(临时,或写入启动脚本)
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/openssl-1.1.1/lib:$LD_LIBRARY_PATH
# 方法3:编译时写死 RPATH(最干净,不依赖环境变量)
# 在 PHP configure 之前设置
export LDFLAGS="-Wl,-rpath,/usr/local/lib -Wl,-rpath,/usr/local/openssl-1.1.1/lib"
---
第七步:各架构特殊处理
龙芯 LoongArch64
# 龙芯的库路径和 x86 不同
# 系统库在 /usr/lib/loongarch64-linux-gnu(Debian系)
# 或 /usr/lib64(RHEL系)
# 编译时加架构标志
export CFLAGS="-O2 -march=loongarch64 -mabi=lp64d"
export CXXFLAGS="-O2 -march=loongarch64 -mabi=lp64d"
# 某些库需要链接 libatomic
export LDFLAGS="-latomic"
# oniguruma 在龙芯上可能需要禁用 JIT
./configure --disable-jit # oniguruma 的 configure
鲲鹏 ARM64
# 鲲鹏支持 LSE 原子指令,可以加速
export CFLAGS="-O2 -march=armv8.2-a+lse"
export CXXFLAGS="-O2 -march=armv8.2-a+lse"
# 如果不确定 CPU 支持的指令集,用保守版本
export CFLAGS="-O2 -march=armv8-a"
申威 SW-64
# 申威架构支持最差,很多库没有优化
# 用最保守的编译参数
export CFLAGS="-O1"
export CXXFLAGS="-O1"
# OpenSSL 在申威上要用通用目标
./Configure linux-generic64 --prefix=/usr/local/openssl-1.1.1 shared
---
第八步:一键验证脚本
#!/bin/bash
# verify_php.sh - 验证 PHP 及所有关键扩展是否正常
PHP_BIN="/usr/local/php/bin/php"
echo "=== PHP 环境验证 ==="
echo ""
# 基本信息
echo "PHP 版本:"
$PHP_BIN -v
echo ""
# 检查关键扩展
echo "扩展状态:"
REQUIRED_EXTS=(
"openssl" "curl" "mbstring" "zip"
"pdo" "pdo_mysql" "mysqli" "redis"
"opcache" "pcntl" "sockets" "bcmath"
"intl" "gd" "sodium" "json"
)
ALL_OK=true
for ext in "${REQUIRED_EXTS[@]}"; do
if $PHP_BIN -m 2>/dev/null | grep -q "^${ext}$"; then
printf " %-15s ✓\n" "$ext"
else
printf " %-15s ✗ 缺失\n" "$ext"
ALL_OK=false
fi
done
echo ""
# 测试 OpenSSL 实际可用
echo "OpenSSL 功能测试:"
$PHP_BIN -r "
\$key = openssl_pkey_new(['private_key_bits' => 2048, 'private_key_type' => OPENSSL_KEYTYPE_RSA]);
if (\$key) {
echo ' RSA 密钥生成: ✓' . PHP_EOL;
} else {
echo ' RSA 密钥生成: ✗ ' . openssl_error_string() . PHP_EOL;
}
echo ' OpenSSL 版本: ' . OPENSSL_VERSION_TEXT . PHP_EOL;
"
# 测试 curl
echo ""
echo "curl 功能测试:"
$PHP_BIN -r "
\$ch = curl_init('https://www.baidu.com');
curl_setopt(\$ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt(\$ch, CURLOPT_TIMEOUT, 5);
curl_setopt(\$ch, CURLOPT_SSL_VERIFYPEER, false);
\$result = curl_exec(\$ch);
\$err = curl_error(\$ch);
curl_close(\$ch);
if (\$result !== false) {
echo ' HTTPS 请求: ✓' . PHP_EOL;
} else {
echo ' HTTPS 请求: ✗ ' . \$err . PHP_EOL;
}
echo ' curl 版本: ' . curl_version()['version'] . PHP_EOL;
echo ' SSL 后端: ' . curl_version()['ssl_version'] . PHP_EOL;
"
# 测试 mbstring
echo ""
echo "mbstring 功能测试:"
$PHP_BIN -r "
\$str = '你好世界';
echo ' 中文字符串长度: ' . mb_strlen(\$str) . ' (应为4)' . PHP_EOL;
echo ' 转换编码: ' . mb_convert_encoding(\$str, 'GBK', 'UTF-8') !== false ? '✓' : '✗';
echo PHP_EOL;
"
echo ""
if $ALL_OK; then
echo "所有关键扩展正常 ✓"
else
echo "有扩展缺失,请检查上方标记 ✗ 的项目"
fi
---
常见报错速查
┌──────────────────────────────────────┬──────────────────────────────┬──────────────────────────────────────┐
│ 报错信息 │ 原因 │ 解决方法 │
├──────────────────────────────────────┼──────────────────────────────┼──────────────────────────────────────┤
│ Cannot find OpenSSL │ openssl-devel 未装或版本不对 │ 装 openssl-devel 或编译指定路径 │
├──────────────────────────────────────┼──────────────────────────────┼──────────────────────────────────────┤
│ error: oniguruma not found │ oniguruma 包名不同 │ 搜包名或从源码编译 │
├──────────────────────────────────────┼──────────────────────────────┼──────────────────────────────────────┤
│ libzip version too old │ 系统 libzip < 1.2.0 │ 从源码编译 libzip 1.10.x │
├──────────────────────────────────────┼──────────────────────────────┼──────────────────────────────────────┤
│ libssl.so.1.1 not found │ 运行时找不到库 │ 加 ldconfig 配置或设 LD_LIBRARY_PATH │
├──────────────────────────────────────┼──────────────────────────────┼──────────────────────────────────────┤
│ SSLv3_client_method not defined │ curl 和 openssl 版本不匹配 │ 重新编译 curl 指定 openssl 路径 │
├──────────────────────────────────────┼──────────────────────────────┼──────────────────────────────────────┤
│ undefined reference to __atomic │ 龙芯/申威原子操作 │ 加 LDFLAGS="-latomic" │
├──────────────────────────────────────┼──────────────────────────────┼──────────────────────────────────────┤
│ configure: error: Cannot find libzip │ libzip-devel 未装 │ dnf install libzip-devel 或源码编译 │
└──────────────────────────────────────┴──────────────────────────────┴──────────────────────────────────────┘
---
核心原则总结
1. 不要替换系统 OpenSSL → 装到 /usr/local/openssl-x.x.x,PHP 编译时指定路径
2. 自编译的库要刷 ldconfig → 否则运行时找不到
3. 不同架构加不同 CFLAGS → 龙芯加 -latomic,鲲鹏可加 LSE 指令
4. 先诊断再动手 → 跑诊断脚本,搞清楚缺什么再装什么
5. PKG_CONFIG_PATH 要设对 → configure 靠它找库的头文件和版本信息
更多推荐


所有评论(0)