php内核 定制内核补丁制作、版本固化管理
最佳方式不是“改完源码就打包”而是“补丁最小化 补丁集管理 可重复构建 版本指纹固化”。forshortcuts 这样你─6─个月后还能复现今天这版私有─PHP─内核。──────────────────────────────────────────────────────────────────────── ---1)大白话先讲明白你到底要管什么 “定制内核补丁 版本固化”本质是管4件事1. 改了什么patch 内容2. 基于哪个上游版本改的base tag/commit3. 用什么环境编出来的编译器、依赖、CFLAGS4. 产物是不是这次改出来的二进制指纹、SBOM、checksum ---2)推荐目录结构直接抄 php-kernel-custom/ upstream/# php-src 上游源码干净patches/ 0001-branding.patch 0002-netguard.patch 0003-module-trim.patch series# 补丁顺序清单build/ Dockerfile.builder build.sh verify.sh manifests/ lock.json# 版本固化清单核心checksums.txt output/ php-custom-8.3.7-linux-x86_64.tar.gz php-custom-8.3.7-linux-x86_64.sha256 ---3)补丁制作最佳方式最稳 规则 - 每个 patch 只做一件事品牌、拦截、安全、裁剪分开 - patch 尽量小只改必要行 - 绝不把“格式化噪音”混进 patch - 提交信息写“为什么改”不是“改了啥” 生成补丁完整命令流# 1) 准备上游源码gitclone https://github.com/php/php-src.gitcdphp-srcgitcheckout php-8.3.7gitswitch-ccustom/php-8.3.7# 2) 做你的改动编辑文件# 例如main/SAPI.c, ext/standard/info.c ...# 3) 提交gitaddmain/SAPI.cgitcommit-msecurity: restrict powered-by header exposure path# 4) 导出补丁gitformat-patch-1HEAD-o../patches 如果你要维护“补丁序列”用 series 文件 patches/series 0001-branding.patch 0002-netguard.patch 0003-module-trim.patch 应用whileread-rp;dogitampatches/$p;donepatches/series ---4)版本固化核心中的核心 做一个 manifests/lock.json把“可变项”全部锁住。 manifests/lock.json 示例{product:php-custom,php_upstream:{tag:php-8.3.7,commit:a1b2c3d4e5f6},patch_series:[{name:0001-branding.patch,sha256:xxx},{name:0002-netguard.patch,sha256:yyy},{name:0003-module-trim.patch,sha256:zzz}],toolchain:{os:rockylinux:9,gcc:11.4.1,make:4.3,autoconf:2.69,bison:3.7.6,re2c:3.0},configure:[--enable-fpm,--enable-opcache,--with-openssl,--with-curl,--with-pdo-mysql,--enable-mbstring,--without-pear],cflags:-O2 -fstack-protector-strong -D_FORTIFY_SOURCE2 -fPIC,ldflags:-Wl,-z,relro -Wl,-z,now}一句话没有 lock.json就不叫版本固化。 ---5)可重复构建完整脚本 build/build.sh#!/usr/bin/env bashset-euopipefailROOT$(cd $(dirname$0)/..pwd) SRC_DIR${ROOT}/upstream/php-src PATCH_DIR${ROOT}/patches OUT_DIR${ROOT}/output LOG_DIR${ROOT}/output/logs PREFIX/opt/php-custom/8.3.7 mkdir -p ${OUT_DIR} ${LOG_DIR} echo [1]resetsourcetree git -C ${SRC_DIR} reset --hard git -C ${SRC_DIR} clean -fd echo [2]checkout locked upstream tag git -C ${SRC_DIR} checkout php-8.3.7 echo [3]apply patch series while read -r p; do [[ -z ${p} ]] continue git -C ${SRC_DIR} am ${PATCH_DIR}/${p} done ${PATCH_DIR}/series echo [4]build php cd ${SRC_DIR} ./buildconf --force ${LOG_DIR}/buildconf.log 21 export CFLAGS-O2-fstack-protector-strong-D_FORTIFY_SOURCE2-fPIC export LDFLAGS-Wl,-z,relro -Wl,-z,now ./configure \ --prefix${PREFIX} \ --enable-fpm \ --enable-cli \ --disable-cgi \ --enable-opcache \ --enable-mbstring \ --with-openssl \ --with-curl \ --with-mysqli \ --with-pdo-mysql \ --without-pear ${LOG_DIR}/configure.log 21 make -j$(nproc) ${LOG_DIR}/make.log 21 make install ${LOG_DIR}/install.log 21 echo [5]package PKG${OUT_DIR}/php-custom-8.3.7-linux-$(uname-m).tar.gz tar -C / -czf ${PKG} opt/php-custom/8.3.7 sha256sum ${PKG} ${PKG}.sha256 echo DONE:${PKG} --- 6) 验证脚本完整 build/verify.sh #!/usr/bin/env bash set -euo pipefail PHP_BIN${1:-/opt/php-custom/8.3.7/bin/php} echo version ${PHP_BIN} -v | head -n 3 echo echo modules required(openssl curl mbstring pdo_mysql mysqli opcache) for ext in ${required[]}; do if ${PHP_BIN} -m | grep -qi ^${ext}$; then echo [OK]${ext} else echo [FAIL]missing${ext} exit 1 fi done echo echo hardening flags ${PHP_BIN} -i | grep -E Configure Command|Thread Safety|Server API || true echo echo smoketest ${PHP_BIN} -r echo ok-.PHP_VERSION.PHP_EOL; echo VERIFY PASSED ---7)升级策略避免每次大出血 从8.3.7 -8.3.81. 切上游 tag2. 重放 patch series3. 有冲突只修冲突 patch不动其他 patch4. 全量跑 verify 回归 压测5. 产出新 lock.json 与 checksum ---8)常见翻车点你提前避开 - 把多个改动揉成一个大 patch后面无法维护 - 没有补丁顺序文件重放结果随机 - 构建机漂移gcc 版本变了产物行为变化 - 只验 php-v不验模块和安全策略 - 没有制品 checksum无法追溯 --- 最后一句话收住 私有 PHP 内核长期可维护的关键不是“会改源码”而是“补丁序列化、构建可重复、版本可追溯、产物可验真”。