根本原因是ZIP解压丢失可执行位且Git不跟踪权限,临时修复用chmod +x vendor/bin/phpunit,一劳永逸需在composer.json中配置post-install-cmd钩子自动赋权。

根本不是脚本本身没权限,而是 vendor/bin/ 下的 PHP 可执行文件在 ZIP 解压时丢了 x 位——Git 不存权限、Composer 不补权限,每次重装都复现。
为什么 vendor/bin/phpunit 执行报 Permission denied
Linux/macOS 下运行 vendor/bin/phpunit 报错,99% 是因为解压后文件权限是 -rw-r--r--,没有可执行位。这不是目录写入失败,也不是 composer install 挂了,只是 shebang 脚本被当普通文本读了。
- 验证:运行
ls -l vendor/bin/phpunit,看第一列有没有x - 确认:运行
head -n1 vendor/bin/phpunit,输出应为#!/usr/bin/env php - 注意:Windows 下该问题不适用
chmod,也无需加x位
临时修复:直接补执行权限
能立刻跑起来,但下次 composer install 或 update 后又失效。
- 单个补:
chmod +x vendor/bin/phpunit - 批量补:
chmod +x vendor/bin/* - CI/部署中慎用:这种手动操作不可靠,容易漏或误触
一劳永逸:用 post-install-cmd 自动赋权
把权限修复变成安装流程的一部分,所有成员和 CI 都自动对齐。
- 编辑
composer.json,在"scripts"下加两行:
"scripts": {
"post-install-cmd": "chmod +x vendor/bin/*",
"post-update-cmd": "chmod +x vendor/bin/*"
}
vendor/bin/ 必须存在,否则命令会失败;建议先确保 vendor/ 权限本身没问题(见下一条)别忘了先检查 vendor/ 所有权是否干净
如果 vendor/ 目录本身是 root 所有,chmod +x 可能被拒绝,或者后续 composer update 生成的新脚本仍无 x 位。
- 查归属:
ls -ld vendor/,确认属主是当前用户(不是root) - 修归属(如需):
sudo chown -R $USER:$USER vendor/ - 再删再装:
rm -rf vendor/ composer.lock && composer install,比硬扛旧权限更稳
最容易被忽略的是:权限修复只解决“能不能执行”,不解决“PHP 解释器在哪”。如果 #!/usr/bin/env php 找不到 CLI PHP,照样报 No such file or directory——这时候得看 which php 和 php -v 是否一致。











