答案:Composer脚本超时由PHP的max_execution_time控制,需通过php -d max_execution_time=0或脚本内set_time_limit()干预;process-timeout对此无效。post-install-cmd等PHP脚本执行超时,应检查是否卡在交互(加--no-interaction)、确认set_time_limit()置于逻辑首行、并排除disable_functions限制。

Composer 脚本超时不是 process-timeout 能管的,它由 PHP 自身控制,必须在脚本内部或 PHP 运行层干预。
post-install-cmd 或自定义脚本卡住报 timeout 怎么办
这类脚本(如 php artisan key:generate、php -r "require 'vendor/autoload.php'; ...")是作为子进程被 Composer 启动的,但执行主体是 PHP 进程,process-timeout 只管“启动是否成功”,不管“PHP 脚本内部跑多久”。一旦脚本本身耗时过长,会触发 PHP 的 max_execution_time 限制,报错类似:Fatal error: Maximum execution time of 30 seconds exceeded。
- 临时绕过:用
php -d max_execution_time=0 composer install,让整个 Composer 进程里的所有 PHP 脚本都不受时间限制 - 精准控制:在脚本入口第一行加
set_time_limit(1200)(单位秒),确保它早于任何可能阻塞的操作执行 - 检查是否卡在交互:加上
--no-interaction参数,避免php artisan key:generate等命令因等待 stdin 输入而挂起 - 注意:不能在
composer.json的config段写timeout或script-timeout字段——这些字段不存在,Composer 会静默忽略
为什么改了 process-timeout 还没用
因为 process-timeout 控制的是外部命令(如 git clone、unzip、sh ./deploy.sh)的启动和运行上限,不覆盖 PHP 脚本内部逻辑。如果你的脚本里有大量文件扫描、数据库迁移或远程 API 轮询,process-timeout 根本不会触发,真正掐断你的是 PHP。
- 验证方式:加
-vvv运行composer install,看卡住时最后输出的是Running command: php ...(PHP 层问题)还是Executing command (CWD): git clone ...(process-timeout问题) - 常见陷阱:某些 CI 环境默认设了
php -d max_execution_time=30,覆盖了你本地配置,得在 CI 配置里显式重置 - 共享主机或容器中,
set_time_limit()可能被disable_functions禁用,需先查php -i | grep disable_functions
如何让自定义 PHP 类脚本支持超时配置
如果脚本封装在类方法里(如 MyBuildScript::run()),最稳妥的做法是在方法开头调用 set_time_limit(),而不是依赖外部参数。
public static function run($event)
{
set_time_limit(1800); // 必须放第一行,且不能被后续代码覆盖
// 后续耗时操作:DB migrate、asset build、vendor scan...
}
- 设为
0表示禁用限制,但仅限可信环境;CI 中建议设明确值(如1800)防止无限挂起 - 不要依赖
ini_set('max_execution_time', '1800')—— 它在 CLI 下无效,只对 Web SAPI 生效 - 若脚本涉及 I/O 密集型操作(如遍历 vendor 目录),还需确认系统 ulimit 和磁盘性能,否则即使 PHP 不超时,也会因
EMFILE或读取延迟卡死
真正容易被忽略的点是:脚本超时和 Composer 主流程超时是两套机制,混用配置项只会白忙;必须分清「谁在执行」——是 Composer 启动的 shell 命令,还是 PHP 进程里跑的逻辑。











