Composer原生不支持脚本并发执行,scripts字段仅顺序调用命令且无并行控制;需借助shell的&、npm-run-all或GNU Parallel等外部工具实现并发,而数组形式如"@lint", "@test"实为依次执行,并非真正并行。

Composer原生不支持脚本并发执行
Composer 的 scripts 字段本身没有并发机制——它只按顺序逐条调用命令,且不提供并行控制开关。所谓“并发执行多个脚本”,必须靠外部工具或 shell 层实现,不是 Composer 自身能力。
常见误解是把 "scripts": { "ci": ["@lint", "@test", "@phpstan"] } 当作并行,其实这只是数组展开后依次执行,和写三行 composer run-script lint 效果完全一样,既不并发,也不中断失败步骤。
用 && 和 & 区分串行与并行
Shell 层才是真正的调度层:&& 保证前一步成功才跑下一步(链式),& 则让命令在后台同时启动(并行)。
-
"build": "php artisan clear && php artisan optimize:autoload && npm run build"—— 串行带中断,任一失败即停 -
"ci": "composer run-script lint & composer run-script test & composer run-script check-types && wait"—— 并行启动,wait确保主进程等待全部结束 - Windows 用户注意:
CMD不支持&&和&;PowerShell 可用;+$?手动判断,但更稳妥的是统一用 Git Bash 或 WSL
复杂并行场景推荐 npm-run-all
当需要跨平台、实时输出、失败控制或混合串/并逻辑时,硬写 shell 容易出错。npm-run-all 是目前最轻量又可靠的方案,它不依赖 Node 项目,纯 CLI 工具。
安装后(npm install -g npm-run-all),在 composer.json 中定义:
"scripts": {
"lint": "phpcs app/",
"test": "phpunit --no-coverage",
"check-types": "phpstan analyse src/",
"ci:check": "run-p -r lint test check-types"
}
run-p -r 表示并行(-p)且实时流式输出(-r),失败默认继续;加 --halt-on-fail 可改为遇错即停。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
注意事项:
- 多个脚本不能共享同一缓存目录(如 PHPStan 和 PHPUnit 同时写
phpstan.neon缓存会冲突) - 内存敏感任务(如大项目静态分析)建议限并发数:
run-p -p -r --jobs 2 lint test check-types - 含交互命令(如
read或dialog)的脚本禁止并行,否则输入混乱
别碰 GNU Parallel,除非你真需要精细调度
parallel 在 Linux/macOS 下确实强大,支持超时、重试、失败策略等,但对绝大多数 PHP 项目属于过度设计。
典型用法:
parallel --jobs 3 composer run-script {} ::: lint test check-types
但要注意:
- CI 环境中它可能因权限或容器限制不可用(比如 GitHub Actions 默认没装)
-
--halt now,fail=1才能实现“一个失败就全停”,默认是忽略失败继续 - 并发数设太高(如
--jobs 8)容易触发临时文件竞争,报file_put_contents(/tmp/): failed to open stream
真正卡在构建速度上的,往往不是并发数不够,而是脚本之间隐式依赖没拆清、缓存没复用、或某一步本身低效(比如没加 --no-dev 就跑 composer install)。先理清流程再谈并发,不然只是把慢动作加速播放。

















