本文介绍在新的 Linux 宝塔服务器上,从安装 OpenCC 底层库和字典开始,到编译、测试、安装并启用 PHP 8.5 的 OpenCC 扩展。底层库负责转换,PHP 扩展提供 opencc_open()、opencc_convert()、opencc_close() 等函数。
版本说明:本文固定使用 OpenCC 1.1.9,以及 opencc4php 提交 9000997ba8b1a4f4935ae8d9ec390f1b4a6b3dc1。这是为了复现本次 PHP 8.5.12 下验证通过的组合,并不表示它们是最新版本。已有服务器完成了扩展编译、64 组转换对比和 CLI/FPM 测试;下文的新服务器全新安装步骤依据上游构建规则整理,不代表已在所有发行版逐一实测。
适用范围:已安装宝塔 Linux 面板和 PHP 8.5 的新服务器,命令使用 Bash,以 root 身份运行。Ubuntu/Debian 与 Rocky Linux、AlmaLinux、CentOS Stream 的依赖安装命令分开提供,选择对应系统的一组即可。本文不适用于 Windows。
已有 OpenCC 的服务器:不要重复执行底层库安装步骤,也不要覆盖现有字典;先核对已有安装前缀,再为 PHP 8.5 单独编译扩展。本文后面有对应说明。本文中的新服务器统一使用 /usr/local 作为底层库安装前缀,与某些老服务器的 /usr/lib、/usr/share/opencc 路径不同。
一、在宝塔安装 PHP 8.5,并检查安装路径
先在宝塔「软件商店 → 运行环境」安装 PHP 8.5。安装后不必立即切换已有网站;可以另建一个测试站点,等扩展验证通过后再使用。以下路径按宝塔默认目录编写。
sudo -i
进入 root 的 Bash 会话后,执行下面的检查。每个命令框应整段复制执行;遇到报错应先处理,不要跳过继续。不要把后面的“预期输出”当作命令执行。
(
set -eu
test "$(id -u)" -eq 0
test -x /www/server/php/85/bin/php
test -x /www/server/php/85/bin/phpize
test -x /www/server/php/85/bin/php-config
/www/server/php/85/bin/php -v
/www/server/php/85/bin/php-config --version
/www/server/php/85/bin/php-config --extension-dir
)
版本应为 8.5.x。务必使用上述绝对路径,不能直接用系统的 phpize、php-config,否则可能编译成其他 PHP 版本的扩展。也不要为了这个扩展安装发行版的 php-dev 来替代宝塔开发文件。
二、安装编译依赖
Ubuntu / Debian
(
set -eu
apt-get update
apt-get install -y build-essential autoconf automake libtool cmake git pkg-config python3 ca-certificates
)
Rocky Linux / AlmaLinux / CentOS Stream
(
set -eu
dnf install -y gcc gcc-c++ make autoconf automake libtool cmake git pkgconf-pkg-config python3 ca-certificates
)
OpenCC 的字典构建需要 Python;关闭文档构建后不需要为了本教程额外安装 Doxygen。上述系统需要能正常使用自己的软件仓库。本教程没有要求升级系统全部软件,也没有要求卸载任何旧版 PHP。
cmake --version
gcc --version
g++ --version
python3 --version
git --version
三、目录规划
| 内容 | 本教程使用的路径 |
|---|---|
| OpenCC 底层源码 | /usr/local/OpenCC |
| 底层库 | /usr/local/lib/libopencc.so* |
| 底层头文件 | /usr/local/include/opencc |
| 转换配置与字典 | /usr/local/share/opencc |
| PHP 8.5 扩展源码及测试文件 | /usr/local/opencc4php-85 |
| PHP 8.5 正式扩展目录 | 通过 /www/server/php/85/bin/php-config --extension-dir 获取 |
| 安装前备份 | /root/opencc85-backup-日期时间 |
OpenCC 底层库、配置和字典可以供多个 PHP 版本共用;PHP 7.4 与 PHP 8.5 的 opencc.so 必须分别编译、分别安装。不能把 7.4 的扩展直接复制到 8.5。
四、下载并编译 OpenCC 底层库(仅全新安装执行)
下面的命令要求 /usr/local/OpenCC 不存在。如果目录已存在,命令会停止,以免把旧环境当作新服务器重新安装。Git 下载失败时应先处理网络问题,不要关闭 HTTPS 证书校验。
(
set -eu
test ! -e /usr/local/OpenCC
git clone --branch ver.1.1.9 --depth 1 --recurse-submodules \
https://github.com/BYVoid/OpenCC.git /usr/local/OpenCC
cmake -S /usr/local/OpenCC -B /usr/local/OpenCC/build-php85 \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DLIB_INSTALL_DIR=/usr/local/lib \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_DOCUMENTATION=OFF \
-DBUILD_PYTHON=OFF \
-DENABLE_GTEST=OFF \
-DENABLE_BENCHMARK=OFF \
-DPYTHON_EXECUTABLE="$(command -v python3)" \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
-DCMAKE_POLICY_DEFAULT_CMP0148=OLD
cmake --build /usr/local/OpenCC/build-php85 --parallel 2
cmake --install /usr/local/OpenCC/build-php85
)
这里固定使用 2 个编译任务,减少编译时的资源占用。兼容性参数用于较新 CMake 构建旧版依赖;较旧 CMake 如果提示这些兼容参数未被使用,应结合最终构建结果判断。底层安装会同时安装库、头文件、转换配置与编译后的字典,不需要再手动下载一份字典。
五、配置动态库搜索路径并验证底层转换
动态库路径应指向放置 libopencc.so 的目录,而不是 PHP 扩展的 modules 目录。新服务器按本教程安装后使用 /usr/local/lib。
(
set -eu
test -e /usr/local/lib/libopencc.so
test -r /usr/local/share/opencc/s2twp.json
if ! grep -Fxq '/usr/local/lib' /etc/ld.so.conf.d/opencc-local.conf 2>/dev/null; then
printf '%s\n' '/usr/local/lib' >> /etc/ld.so.conf.d/opencc-local.conf
fi
ldconfig
ldconfig -p | grep opencc
ldd /usr/local/bin/opencc
cd /usr/local/share/opencc
printf '%s\n' '我的鼠标哪儿去了?' | /usr/local/bin/opencc -c /usr/local/share/opencc/s2twp.json
)
上面的转换预期输出:
我的滑鼠哪兒去了?
同时确认 ldd 输出中没有 not found。在底层命令行转换还不能正常工作时,先不要继续排查 PHP。
六、下载并为 PHP 8.5 编译扩展
底层库是 OpenCC 官方项目;opencc4php 是社区维护的 PHP 绑定。下面固定使用本次已经编译验证的源码提交,不改动其源码。
(
set -eu
test ! -e /usr/local/opencc4php-85
git clone https://github.com/nauxliu/opencc4php.git /usr/local/opencc4php-85
cd /usr/local/opencc4php-85
git checkout --detach 9000997ba8b1a4f4935ae8d9ec390f1b4a6b3dc1
/www/server/php/85/bin/phpize
./configure \
--with-php-config=/www/server/php/85/bin/php-config \
--with-opencc=/usr/local \
--with-libdir=lib
make -j2
test -f modules/opencc.so
ldd modules/opencc.so
)
--with-opencc 指向的是包含 include/opencc 与 lib 的安装前缀,这里是 /usr/local,不是源码目录 /usr/local/OpenCC。再次确认 ldd 没有 not found。到这一步只是编译,尚未安装或启用 PHP 扩展。
七、临时加载与测试,先不修改 php.ini
/www/server/php/85/bin/php -n \
-d extension=/usr/local/opencc4php-85/modules/opencc.so \
--ri opencc
预期能看到 opencc support => enabled。这里的 -n 只让本次 CLI 测试忽略 INI 文件,不会修改线上配置,也不会重启 PHP。
继续运行扩展随附测试。这个方式不需要从线上 disable_functions 中删除 proc_open 或 shell_exec。
(
set -eu
cd /usr/local/opencc4php-85
TEST_PHP_EXECUTABLE=/www/server/php/85/bin/php \
NO_INTERACTION=1 REPORT_EXIT_STATUS=1 \
/www/server/php/85/bin/php -n run-tests.php -n \
-d extension=/usr/local/opencc4php-85/modules/opencc.so tests
)
本次测试组合的两个随附测试均通过。新服务器也应查看最终统计是否为 Tests failed: 0;测试失败时不要直接安装。随附测试数量少,仍需要下面的转换测试与网页验证。
创建一个测试文件,检查 8 种转换配置以及反复打开、转换、关闭操作。测试文件使用完整配置路径,并固定测试时的工作目录,避免读取到当前目录下同名的配置或字典。
cat > /usr/local/opencc4php-85/verify.php <<'PHP'
<?php
declare(strict_types=1);
$directory = '/usr/local/share/opencc';
if (!extension_loaded('opencc')) {
throw new RuntimeException('OpenCC extension is not loaded');
}
if (!chdir($directory)) {
throw new RuntimeException('Cannot enter OpenCC dictionary directory');
}
$configs = ['s2t', 't2s', 's2tw', 'tw2s', 's2hk', 'hk2s', 's2twp', 'tw2sp'];
$text = '我的鼠标哪儿去了?伺服器、軟體、頭髮與發展。';
foreach ($configs as $config) {
$handle = opencc_open($directory . '/' . $config . '.json');
if ($handle === false) {
throw new RuntimeException('open failed: ' . $config . ' ' . opencc_error());
}
try {
$result = opencc_convert($text, $handle);
if ($result === false) {
throw new RuntimeException('convert failed: ' . opencc_error());
}
echo $config, ': ', $result, PHP_EOL;
} finally {
opencc_close($handle);
}
}
for ($i = 0; $i < 100; $i++) {
$handle = opencc_open($directory . '/s2twp.json');
if ($handle === false) {
throw new RuntimeException('repeat open failed');
}
try {
if (opencc_convert('我的鼠标哪儿去了?', $handle) !== '我的滑鼠哪兒去了?') {
throw new RuntimeException('unexpected conversion result');
}
} finally {
opencc_close($handle);
}
}
echo 'PHP ', PHP_VERSION, ' / OpenCC test passed', PHP_EOL;
PHP
/www/server/php/85/bin/php -n \
-d extension=/usr/local/opencc4php-85/modules/opencc.so \
/usr/local/opencc4php-85/verify.php
八、备份 PHP 8.5 配置与已有扩展
临时加载测试通过后再安装。下面会备份 PHP 8.5 的配置目录;若原来已经有 opencc.so,同时备份旧文件。备份路径保存到扩展源码目录,后续可以据此回滚。不会复制或修改 PHP 7.4 的文件。
(
set -eu
BACKUP="/root/opencc85-backup-$(date +%Y%m%d-%H%M%S)"
EXT_DIR="$(/www/server/php/85/bin/php-config --extension-dir)"
test ! -e "$BACKUP"
install -d -m 700 "$BACKUP"
cp -a /www/server/php/85/etc "$BACKUP/etc"
printf '%s\n' "$EXT_DIR" > "$BACKUP/extension-dir.txt"
if [ -f "$EXT_DIR/opencc.so" ]; then
cp -a "$EXT_DIR/opencc.so" "$BACKUP/opencc.so"
else
touch "$BACKUP/extension-was-absent"
fi
printf '%s\n' "$BACKUP" > /usr/local/opencc4php-85/backup-path.txt
printf 'Backup directory: %s\n' "$BACKUP"
)
九、安装扩展并写入 PHP 8.5 配置
扩展目录通过对应版本的 php-config 动态获取,不写死 API 目录编号。下面只安装一个扩展文件,不运行底层 OpenCC 的安装命令。
(
set -eu
EXT_DIR="$(/www/server/php/85/bin/php-config --extension-dir)"
install -d -m 755 "$EXT_DIR"
install -m 755 /usr/local/opencc4php-85/modules/opencc.so "$EXT_DIR/opencc.so.new"
mv -f "$EXT_DIR/opencc.so.new" "$EXT_DIR/opencc.so"
sha256sum /usr/local/opencc4php-85/modules/opencc.so "$EXT_DIR/opencc.so"
)
两个文件的 SHA256 应一致。然后为 PHP 8.5 启用扩展。宝塔可能让 CLI 使用独立的 php-cli.ini;如果该文件存在,下面也会为它添加同一配置。
(
set -eu
for INI in /www/server/php/85/etc/php.ini /www/server/php/85/etc/php-cli.ini; do
[ -f "$INI" ] || continue
if ! grep -E '^[[:space:]]*extension[[:space:]]*=' "$INI" | grep -q 'opencc'; then
printf '\n; OpenCC extension for PHP 8.5\nextension = opencc.so\n' >> "$INI"
fi
done
/www/server/php/85/bin/php --ini
/www/server/php/85/bin/php --ri opencc
/www/server/php/85/sbin/php-fpm -t -y /www/server/php/85/etc/php-fpm.conf
)
实际需要的配置项只有下面这一行,不能在同一生效配置中重复添加:
extension = opencc.so
更正旧教程:extension = opencc.so 和 extension=opencc.so 都是合法 INI 写法,等号两边的空格不是加载成功与否的条件;[openCC] 分节标题也不是必需项。真正要核对的是扩展版本、路径、依赖库,以及 CLI/FPM 实际使用的配置。
十、重新加载 PHP 8.5,并验证默认 CLI
先确认前一步 FPM 配置检查成功。然后在宝塔「软件商店 → PHP 8.5 → 设置 → 服务」重新加载配置或重启 PHP 8.5。只操作 8.5,不操作 7.4。也可以在存在对应脚本时使用下面的平滑重载命令。
(
set -eu
test -x /etc/init.d/php-fpm-85
/etc/init.d/php-fpm-85 reload
/www/server/php/85/bin/php --ri opencc
/www/server/php/85/bin/php /usr/local/opencc4php-85/verify.php
)
这里不再使用 -n 或临时 -d extension=...。如果仍显示测试通过,说明默认 CLI 配置已经生效;网页端还需要下一步单独验证。
十一、验证网页端 PHP 8.5 / FPM
在宝塔中新建或选择一个测试站点,把这个测试站点的 PHP 版本设为 8.5。在站点根目录创建 opencc-test.php,粘贴下面的代码,然后通过浏览器访问。这个步骤只针对测试站点,不要求把正式业务站立即切换到 8.5。
<?php
declare(strict_types=1);
header('Content-Type: text/plain; charset=utf-8');
echo 'PHP: ', PHP_VERSION, PHP_EOL;
echo 'SAPI: ', PHP_SAPI, PHP_EOL;
echo 'OpenCC: ', extension_loaded('opencc') ? 'enabled' : 'disabled', PHP_EOL;
if (!extension_loaded('opencc')) {
http_response_code(500);
exit('OpenCC is not loaded');
}
$directory = '/usr/local/share/opencc';
$previousDirectory = getcwd();
if (!chdir($directory)) {
throw new RuntimeException('Cannot enter OpenCC dictionary directory');
}
$handle = false;
try {
$handle = opencc_open($directory . '/s2twp.json');
if ($handle === false) {
throw new RuntimeException('open failed: ' . opencc_error());
}
$result = opencc_convert('我的鼠标哪儿去了?', $handle);
if ($result === false) {
throw new RuntimeException('convert failed: ' . opencc_error());
}
echo 'Result: ', $result, PHP_EOL;
} finally {
if ($handle !== false) {
opencc_close($handle);
}
if ($previousDirectory !== false) {
chdir($previousDirectory);
}
}
预期网页显示类似下面的内容,其中 PHP 应为实际安装的 8.5.x:
PHP: 8.5.x
SAPI: fpm-fcgi
OpenCC: enabled
Result: 我的滑鼠哪兒去了?
验证完成后,删除测试站点根目录中的 opencc-test.php。无需公开完整 phpinfo()。安装扩展不等于业务程序已兼容 PHP 8.5,正式切换网站前仍需测试原来的接口与任务。
十二、常用转换模式与程序调用
| 配置 | 用途 |
|---|---|
s2t.json | 简体 → 繁体 |
t2s.json | 繁体 → 简体 |
s2tw.json | 简体 → 台湾正体 |
tw2s.json | 台湾正体 → 简体 |
s2hk.json | 简体 → 香港繁体 |
hk2s.json | 香港繁体 → 简体 |
s2twp.json | 简体 → 台湾正体,并转换台湾常用词汇 |
tw2sp.json | 台湾正体 → 简体,并转换大陆常用词汇 |
输入字符串应为 UTF-8。一般调用顺序是打开转换配置、转换、关闭句柄。信息页的书名与正文可以选择不同的转换模式,但同一功能应保持配置及字典版本一致。
工作目录说明:OpenCC 1.1.9 的字典查找会先尝试工作目录中的同名文件。指定 JSON 配置绝对路径有助于定位配置,但并不完全消除相对字典文件的工作目录影响。因此测试例子在转换期间进入统一字典目录,并在网页例子中恢复原目录;不建议在业务程序中永久改变工作目录。不要在站点或任务工作目录随意放置同名字典。
十三、已有 OpenCC / PHP 7.4 的服务器怎么处理
已存在并正常工作的底层库和字典可以继续共用。先只读检查现有位置:
ldconfig -p | grep opencc
ls -ld /usr/include/opencc /usr/local/include/opencc 2>/dev/null
ls -ld /usr/share/opencc /usr/local/share/opencc 2>/dev/null
/www/server/php/74/bin/php --ri opencc
如果现有库和头文件分别位于 /usr/lib、/usr/include/opencc,编译扩展时使用 --with-opencc=/usr;若实际库在 /usr/lib64,同时使用 --with-libdir=lib64。如果现有库装在 /usr/local,则沿用本文主流程的安装前缀。对头文件缺失的旧环境,不要直接重装或升级底层库,应先获取与现有库匹配的开发文件。
例如,底层安装前缀是 /usr 且库目录是 /usr/lib 时,第六步的配置命令改为:
./configure \
--with-php-config=/www/server/php/85/bin/php-config \
--with-opencc=/usr \
--with-libdir=lib
同时把测试代码中的字典目录改为实际位置,例如 /usr/share/opencc。不要把现有 /usr/local/opencc4php 目录用于 8.5 的重新编译;8.5 单独使用 /usr/local/opencc4php-85。这样就能保留 7.4 的扩展和配置,两个版本链接同一底层库、读取同一字典。
十四、常见错误与排查
1. Unable to load dynamic library / libopencc.so 找不到
ldd /usr/local/opencc4php-85/modules/opencc.so
ldconfig -p | grep opencc
cat /etc/ld.so.conf.d/opencc-local.conf
/www/server/php/85/bin/php --ini
检查真实的 libopencc.so* 所在目录,必要时按第五步更新对应动态库路径并运行 ldconfig。不要把 PHP 的 modules 目录误当作底层库目录,也不要用不匹配的库文件强行创建软链接。
2. Module compiled with module API 不一致
说明扩展不是用当前 PHP 8.5 的开发工具编译的。应在独立的 8.5 扩展源码目录重新运行正确路径的 phpize 和 php-config,而不是复制其他 PHP 版本的扩展。已有目录需要先保留日志或备份;确定是本文的 8.5 源码目录后,才执行下面的清理与重编译命令。
(
set -eu
cd /usr/local/opencc4php-85
/www/server/php/85/bin/phpize --clean
/www/server/php/85/bin/phpize
./configure \
--with-php-config=/www/server/php/85/bin/php-config \
--with-opencc=/usr/local \
--with-libdir=lib
make -j2
)
旧服务器应按第十三节把安装前缀及库目录改成实际值。重编译后从临时加载测试开始重新验证,再安装。
3. 测试提示 proc_open / shell_exec 被禁用
使用第七节中 php -n run-tests.php -n ... 的测试方式即可。不要为了测试工具永久开放业务 PHP 的这些函数,也不要把 -n 当作正式网站的配置。
4. CLI 成功,网页仍然没有 opencc
检查测试站是否确实使用 PHP 8.5、FPM 是否重新加载,以及 CLI 是否读取了不同的 php-cli.ini。网页中的 PHP_VERSION、PHP_SAPI 与 extension_loaded() 更能说明该网页请求的实际运行环境。
5. opencc_open 返回 false / 找不到字典
先查看 opencc_error(),再检查配置和字典实际位置、JSON 中引用的字典是否存在,以及运行用户的目录遍历与文件读取权限。正常安装通常目录为 755、数据文件为 644,无须设置 777。若 FPM 配置了 open_basedir,还需确认字典目录在允许范围内;不要直接关闭所有目录限制。
6. 更换服务器后,个别转换结果变化
对比 OpenCC 底层版本、配置模式、字典内容和工作目录。仅仅函数名相同,不保证不同字典版本的所有词语转换都一致;有自定义词库时,应单独保存并校验,不能用新版本默认词库覆盖后假定结果不变。
十五、需要时如何回滚 PHP 8.5 扩展
只在需要撤销本次扩展安装时执行。下面恢复安装前的 PHP 8.5 INI 文件和扩展文件,不卸载底层 OpenCC,不改字典,也不处理 7.4。若安装后又调整过其他 PHP 8.5 配置,先比较备份与现状,避免整体恢复旧 INI 覆盖后续改动。
(
set -eu
BACKUP="$(cat /usr/local/opencc4php-85/backup-path.txt)"
test -d "$BACKUP/etc"
EXT_DIR="$(cat "$BACKUP/extension-dir.txt")"
test "$EXT_DIR" = "$(/www/server/php/85/bin/php-config --extension-dir)"
for NAME in php.ini php-cli.ini; do
if [ -f "$BACKUP/etc/$NAME" ]; then
cp -a "$BACKUP/etc/$NAME" "/www/server/php/85/etc/$NAME"
fi
done
if [ -f "$BACKUP/opencc.so" ]; then
cp -a "$BACKUP/opencc.so" "$EXT_DIR/opencc.so"
elif [ -f "$BACKUP/extension-was-absent" ]; then
rm -f "$EXT_DIR/opencc.so"
fi
/www/server/php/85/sbin/php-fpm -t -y /www/server/php/85/etc/php-fpm.conf
/etc/init.d/php-fpm-85 reload
/www/server/php/85/bin/php -m
)
参考资料
OpenCC 官方项目;opencc4php 扩展项目;旧版安装教程。
发布者:彬彬笔记,转载请注明出处:https://www.binbinbiji.com/jianzhanjiaoliu/3808.html