Post-install脚本失败主因是环境缺失而非扩展未装,需检查phpize、php-config、opcache CLI启用、开发包安装及权限配置。

Post-install 脚本失败不是扩展没装,是环境没准备好
Composer 的 post-install-cmd 或 post-update-cmd 执行失败,90% 不是因为 PHP 扩展本身编译不过,而是脚本运行时缺失关键依赖、权限受限、或 PHP CLI 配置与 Web 环境不一致。比如 ext-redis 安装后触发的 phpize && ./configure && make install,若系统没装 autoconf、make 或对应开发头文件(如 php-devel 或 php-dev),就会静默退出或报错 command not found / phpize: not found。
- 先确认 PHP CLI 是否启用了
opcache:运行php -d opcache.enable_cli=1 -m | grep opcache,没输出说明 CLI 模式下被禁用——某些 Docker 镜像或自定义php.ini会关掉它,导致脚本解析慢甚至超时 - 检查
php-config是否在$PATH中:which php-config;若无,需安装对应开发包(CentOS/RHEL:yum install php-devel;Ubuntu/Debian:apt install php-dev) - 确保
phpize可执行且版本匹配:phpize --version输出应与当前php -v主版本一致(如 PHP 8.2 对应phpize 8.2),否则编译会链接错误 - 避免在 root 用户外执行需要写入
extension_dir的脚本——加sudo不解决根本问题,应改用composer config -g process-timeout 600并确保目标目录可写(如/usr/lib/php/20221212/)
哪些 post-install 命令真能自动装扩展,哪些只是“假装在干活”
不是所有声明了 "post-install-cmd" 的包都能真正完成扩展编译安装。很多脚本只是调用 pecl install 或简单 cp,但 PECL 本身依赖网络、PHP 版本兼容性、以及是否启用 allow_url_fopen。例如 igbinary、msgpack 的官方 composer.json 中常见如下写法:
"scripts": {
"post-install-cmd": [
"@php -r \"if (!extension_loaded('igbinary')) { system('pecl install igbinary'); }\""
]
}
这类命令问题在于:
-
pecl install默认走pecl.php.net,国内直连大概率超时或返回 404;它不读 Composer 镜像配置,换源无效 - PECL 包名与 Composer 包名不一致(如
ext-igbinary对应 PECL 的igbinary),版本约束无法对齐,容易装错 - 未指定
-f(force)参数时,已存在同名扩展会跳过,但不会提示“已存在”,看起来像没执行 - 某些扩展(如
yaml)要求先apt install libyaml-dev,脚本里不检查就直接pecl install,必然失败
真正可控的扩展安装方式:用脚本 + 条件判断 + fallback
想让 post-install-cmd 稳定生效,必须放弃“一条命令打天下”的思路,改用带检测、带 fallback、带日志的 shell 或 PHP 脚本。推荐结构如下:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
立即学习“PHP免费学习笔记(深入)”;
- 先判断扩展是否已加载:
php -m | grep -q 'redis',命中则跳过 - 再检查必要工具是否存在:
command -v phpize >/dev/null 2>&1 || { echo "phpize missing"; exit 1; } - 用
php-config --extension-dir获取真实扩展目录,避免硬编码路径 - 下载预编译包(如 GitHub Releases)比现场编译更可靠:
curl -sL https://github.com/phpredis/phpredis/releases/download/6.0.2/phpredis-6.0.2.tar.gz | tar -xz -C /tmp/ - 最后执行编译链:
cd /tmp/phpredis-6.0.2 && phpize && ./configure && make && sudo make install
把上述逻辑写成独立脚本(如 bin/install-redis-ext),再在 composer.json 中引用:"post-install-cmd": ["./bin/install-redis-ext"]。这样既可调试,也方便 CI 中复用。
CI/CD 中最容易被忽略的三个点
本地能跑通的 post-install 脚本,在 GitHub Actions、GitLab CI 或 Jenkins 上常失败,核心差异不在代码,而在环境初始化阶段:
- 基础镜像没装构建工具:Alpine 镜像默认无
make、gcc、autoconf,得先apk add --no-cache build-base autoconf automake autoheader - PHP 是从源码编译的,但没启用
--enable-maintainer-zts或--with-pic,导致部分扩展(如grpc)链接失败,错误信息常为undefined reference to pthread_* - 脚本里用了
sudo,但 CI runner 默认不允许提权——应改用docker run --user root启动容器,或改用非特权用户可写的临时扩展目录(如/tmp/php-ext),再通过php -d extension=/tmp/php-ext/redis.so测试
扩展自动安装成功率低,本质是把“系统级操作”塞进了“包管理流程”。它不靠多试几次,而靠提前暴露并收敛环境差异。每次失败,优先查 php-config --version、ls -l $(php-config --extension-dir)、php -i | grep 'extension_dir' 这三行输出,比重跑 composer install 有用得多。


















