本文介紹在新的 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/zh-hant/jianzhanjiaoliu/3808.html