composer exec phpunit 报“Command not found”是因为它仅查找当前项目 vendor/bin/ 下的可执行文件,常见原因包括:全局安装、未声明 bin 字段、未执行 install/update、Windows 下 .bat 文件异常;参数需用 -- 隔开;它自动适配平台并临时扩展 PATH,但不支持完整 TTY 交互。

composer exec 能直接运行 vendor/bin/ 下的工具,不用记路径、不care系统差异,但必须在项目根目录下执行,且只认本地装的包。
为什么 composer exec phpunit 有时报 “Command not found”
这不是 Composer 报错,而是它真没在 vendor/bin/ 里找到对应文件。常见原因有:
- 包是用
composer global require装的——composer exec只查当前项目的vendor/bin,不看全局路径 -
composer.json的"bin"字段没声明可执行文件,哪怕代码里有 CLI 入口,composer exec也看不到 - 没跑过
composer install或composer update,vendor/bin目录还是空的 - Windows 下某些包只提供了
.bat,但文件权限不对或被杀毒软件拦截,手动检查vendor/bin/phpunit.bat是否存在且可读
composer exec 怎么传参数给底层命令
参数必须用双横线 -- 隔开,否则会被 composer exec 自己吃掉:
composer exec phpunit -- --filter=testLogin
--timeout=0 是给 composer exec 用的(0 表示不限时),适合跑长任务;--working-dir 可临时切换工作目录,但极少需要。
如果项目 composer.json 里定义了自定义脚本名,比如:
"scripts": { "lint": "php-cs-fixer fix" }
那 composer exec lint 也能用,但它优先级低于 vendor/bin/ 下真实存在的同名二进制。
和直接运行 ./vendor/bin/phpunit 有什么区别
关键不在“能不能跑”,而在“怎么跑得稳”:
-
composer exec会把vendor/bin临时加进PATH,所以脚本内部再调其他 Composer 工具(比如phpcs调php-cs-fixer)大概率能成功;而直接调用路径,容易因子命令找不到而失败 - Windows 下
composer exec phpunit自动选.bat,Linux/macOS 自动选 shell 脚本;你手动写./vendor/bin/phpunit在 Windows 上可能直接报错 - CI 脚本里硬编码
./vendor/bin/路径,换平台就挂;composer exec是跨平台一致的调用方式
最容易被忽略的是:composer exec 不支持交互式 TTY 完整接管,比如 composer exec psysh 很可能卡住输入——这种场景老老实实去跑 vendor/bin/psysh 更靠谱。











