一套“能落地”的:PHP 内核(php-src)做海外冗余模块裁剪 + 无用组件移除,全大白话 + 完整脚本模板。 --- 先一句结论: 最佳方式不是直接删源码文件,而是“配置层禁用优先 + 构建参数裁剪 + 扩展白名单 + 自动验收”。 这样升级 PHP 小版本时成本最低,不容易炸。 ---1)大白话先讲清楚:什么叫“裁剪” 你要做的不是“让 PHP 变残废”,而是: - 只保留业务真用到的能力(白名单) - 去掉海外场景不需要的协议/扩展/工具链绑定 - 减少攻击面、内存占用、镜像体积、冷启动时间 ---2)裁剪三层法(推荐) 第1层:运行配置层(最稳) 先不动源码,先在 php.ini 和启动参数里关掉不用的扩展与能力。 优点:可回滚、风险小。 第2层:编译参数层(核心) ./configure 时只开白名单模块,其他一律不编。 优点:真正减体积、减依赖、减漏洞面。 第3层:源码层(最后手段) 只在“明确永远不用 + 有长期维护能力”时,才做 patch 删除或改 config.m4。 优点:极致瘦身;缺点:升级冲突成本高。 ---3)海外常见“可裁剪对象”(按场景) ▎ 不是让你全关,是给你排查清单。 - 多余数据库驱动:pgsql、odbc、sqlite、pdo_xxx - 冷门协议:snmp、soap、xmlrpc(老) - 老加密/目录服务:ldap、imap、gmp(看业务) - 图像链路:gd、imagick(无图像处理可关) - 压缩归档:zip、bz2(不用就关) - 进程控制:pcntl、sysv*(FPM 场景常可不带) - 调试开发扩展:xdebug、phpdbg(生产关) - expose_php、危险函数、多余 stream wrapper(配置层收紧) ---4)最佳落地流程(完整)1. 先盘点线上真实调用(扩展使用率)2. 生成扩展白名单(allowlist)3. 按白名单编译最小 PHP4. 跑回归测试 + 压测5. 灰度发布6. 保留可快速回滚的标准版镜像 ---5)完整脚本:自动生成“扩展使用画像” 文件:collect_php_extension_usage.php<?php declare(strict_types=1);/** * 扫描代码里常见函数/类,推断依赖的 PHP 扩展。 * 用于裁剪前盘点,不保证100% 精准,但够做第一轮白名单。 */$root=$argv[1]?? getcwd();if(!is_dir($root)){fwrite(STDERR,"Invalid path: {$root}\n");exit(1);}$map=['curl_'=>'curl','mysqli_'=>'mysqli','PDO'=>'pdo','Redis'=>'redis','Memcached'=>'memcached','imagick'=>'imagick','imagecreate'=>'gd','openssl_'=>'openssl','sodium_'=>'sodium','ldap_'=>'ldap','snmp_'=>'snmp','imap_'=>'imap','SoapClient'=>'soap','simplexml_'=>'simplexml','xml_'=>'xml','mb_'=>'mbstring','intl'=>'intl','zip_'=>'zip','gz'=>'zlib','pcntl_'=>'pcntl','posix_'=>'posix',];$rii=new RecursiveIteratorIterator(new RecursiveDirectoryIterator($root, FilesystemIterator::SKIP_DOTS));$hits=[];$totalFiles=0;foreach($riias$file){if(!$file->isFile())continue;$path=$file->getPathname();if(!preg_match('/\.(php|phtml|inc)$/i',$path))continue;$totalFiles++;$content=@file_get_contents($path);if($content===false)continue;foreach($mapas$needle=>$ext){if(stripos($content,$needle)!==false){$hits[$ext]=($hits[$ext]??0)+1;}}}ksort($hits);echo"Scanned files: {$totalFiles}\n";echo"Potential extension usage:\n";foreach($hitsas$ext=>$count){echostr_pad($ext,16)." : {$count}\n";}---6)完整脚本:最小化编译(白名单方式) 文件:build_min_php.sh#!/usr/bin/env bashset-euopipefail# 用法:# ./build_min_php.sh /path/to/php-src /opt/php-min## 思路:# - 只开启业务白名单# - 默认关闭大部分非必须模块# - FPM 生产常见配置模板PHP_SRC="${1:-}"PREFIX="${2:-/opt/php-min}"if[[-z"${PHP_SRC}"||!-d"${PHP_SRC}"]];thenecho"Usage:$0/path/to/php-src [/install/prefix]"exit1ficd"${PHP_SRC}"# 可按业务改白名单./buildconf--force./configure\--prefix="${PREFIX}"\--enable-fpm\--with-fpm-user=www-data\--with-fpm-group=www-data\--disable-cgi\--enable-opcache\--enable-mbstring\--enable-intl\--enable-bcmath\--with-zlib\--with-openssl\--with-curl\--with-pdo-mysql\--with-mysqli\--enable-sockets\--enable-exif\--disable-phpdbg\--without-pearmake-j"$(nproc)"makeinstallecho"Build done:${PREFIX}/bin/php""${PREFIX}/bin/php"-v"${PREFIX}/bin/php"-m---7)完整脚本:裁剪验收(防误删) 文件:verify_min_php.sh#!/usr/bin/env bashset-euopipefailPHP_BIN="${1:-/opt/php-min/bin/php}"if[[!-x"${PHP_BIN}"]];thenecho"php bin not found:${PHP_BIN}"exit1fiecho"== Version ==""${PHP_BIN}"-v|head-n2echoecho"== Required extensions check =="required=(opensslcurlmbstring intl pdo_mysql mysqli zlib opcache)forextin"${required[@]}";doif"${PHP_BIN}"-m|grep-qi"^${ext}$";thenecho"[OK]${ext}"elseecho"[FAIL] missing${ext}"exit2fidoneechoecho"== Forbidden extensions check =="forbidden=(snmp imap ldap odbc pgsql pdo_pgsql)forextin"${forbidden[@]}";doif"${PHP_BIN}"-m|grep-qi"^${ext}$";thenecho"[FAIL] should be removed:${ext}"exit3elseecho"[OK] not loaded:${ext}"fidoneechoecho"All checks passed."---8)生产配置最小化示例(php.ini 关键项) expose_php=Off display_errors=Off log_errors=On;按业务收紧 disable_functions=exec,passthru,shell_exec,system,proc_open,popen allow_url_fopen=Off allow_url_include=Off;性能opcache.enable=1opcache.enable_cli=0opcache.validate_timestamps=0---9)你最关心的“最佳方式”一句话版 白名单编译 + 自动验收 + 灰度发布 是最优解, 不是“看着不爽就删源码”。源码级删除只做最后10% 极限瘦身。 ---10)常见翻车点(提前避坑) - 误删 intl/mbstring 导致多语言、金额、日期格式异常 - 误删 openssl/curl 导致支付、OAuth、第三方 API 全挂 - 只在功能测试通过,没做压测(P99 延迟突然变坏) - 线上没保留标准版镜像,回滚慢 --- 如果你下一条把你的业务栈告诉我(比如 Laravel/Hyperf/WordPress/自研 API 网关),我可以直接给你一份“该栈专用的扩展白名单清单”。