composer exec 不是官方命令,自 composer 2.0+ 起已被移除;所谓“能用”实为第三方插件残留、误用 run-script 或 shell 直接调用所致;唯一官方类似功能是 composer global exec,仅限全局包且不兼容 vendor/bin。

composer exec 不是官方命令,它在 Composer 2.0+ 中已被移除,直接运行会报 Command "exec" is not defined。你看到的“能用”,大概率是本地装了第三方插件(如 hirak/prestissimo 旧版残留),或误将 composer run-script、composer global exec 混淆了。
为什么 composer exec phpunit 有时能跑通
这不是 Composer 原生能力,而是以下三种情况之一:
- 项目里装了非官方插件(如
composer require --dev hirak/prestissimo),它注入了exec子命令——但该插件已废弃多年,且与 Composer 2.5+ 不兼容 - 你实际执行的是
composer run-script phpunit,而composer.json里恰好定义了"phpunit": "php ./vendor/bin/phpunit" - 系统 PATH 中存在全局安装的
phpunit,你敲的其实是 shell 直接调用,和 Composer 无关
composer global exec 是唯一官方支持的类似功能
Composer 5.4+(2026 年主流版本)确实提供了 composer global exec,但它只作用于全局安装包,和 vendor/bin/ 无关:
- 必须先
composer global require phpunit/phpunit,否则报Command "phpunit" is not defined - 它自动识别
~/.composer/vendor/bin/(Linux/macOS)或%APPDATA%\Composer\vendor\bin\(Windows),不依赖 PATH - 参数仍需用
--分隔:composer global exec phpunit -- --filter=testLogin - 不支持交互式命令(如
psysh),卡输入是正常现象
真正安全、跨平台、无需插件的替代方案
别依赖 exec,用这三种方式之一:
-
直接调二进制:用
php ./vendor/bin/phpunit(加php前缀可绕过 Windows.bat权限问题,也避免 shebang 失效) -
走 scripts 定义:在
composer.json里写"scripts": {"test": "php ./vendor/bin/phpunit"},然后跑composer test -
用 npx(Node.js 项目适用):如果项目有
package.json,且工具已通过npm install --save-dev phpunit/phpunit或npx phpunit自动解析 bin,则更轻量
最容易被忽略的是:很多人反复试 composer exec 却没检查自己 Composer 版本(composer --version),也没确认是否真装了对应包到 vendor/bin/——空目录下任何 exec 都只是徒劳。











