composer install 后 bin 脚本无执行权限,因 zip/git 不保留 unix 权限;linux/macos 需 chmod +x vendor/bin/*,windows 应用 php vendor/bin/phpunit;ci/docker 中需显式补权限并避免平台敏感命令。

composer install 后 bin 脚本没权限执行?检查 vendor/bin/ 下文件的可执行位
Composer 安装完含 bin 的包(如 phpunit/phpunit、laravel/installer)后,直接运行 vendor/bin/phpunit 报 Permission denied,不是脚本写错了,而是 Linux/macOS 下文件缺少 x 权限位。Windows 不校验该位,所以本地开发可能不报错,CI 或部署时突然失败。
原因很简单:composer install 默认从 ZIP 或 Git 拉取源码,而 ZIP 格式不保留 Unix 文件权限;Git 仓库若未显式 git update-index --chmod=+x 设置可执行位,检出后文件就是不可执行的。
- 手动修复:运行
chmod +x vendor/bin/*(仅限当前项目) - 一劳永逸:在
composer.json的scripts中加 post-install-cmd:"chmod +x vendor/bin/*"(注意:仅对 POSIX 系统有效,Windows 会跳过) - 更健壮的做法是让包作者在
composer.json里声明"bin": ["bin/phpunit"]并确保 Git 中该文件已+x—— 你只需确认上游 repo 的bin/文件权限正确
Windows 上 vendor/bin/ 脚本为什么根本找不到?别依赖 shebang 行
Linux/macOS 的 #!/usr/bin/env php 在 Windows 上无效,且 Composer 默认把 bin 脚本注册为 .bat 或 .cmd 包装器,但前提是包作者显式提供了 Windows 兼容入口。很多包只写了 Unix 风格脚本,导致 vendor/bin/phpunit 在 Windows CMD/PowerShell 里直接报“不是内部或外部命令”。
这不是权限问题,是执行机制差异:
- Composer 本身不会自动为 Unix
bin脚本生成 Windows 包装器 —— 这事得包作者自己做(例如symfony/console就自带.bat文件) - Windows 用户应优先用
php vendor/bin/phpunit显式调用,而非直接vendor/bin/phpunit - 若项目需跨平台 CI,建议统一用
php命令前缀,或在composer.json的scripts里定义平台无关的 alias:"test": "php vendor/bin/phpunit"
post-install-cmd 脚本在不同系统上行为不一致?避免硬编码路径和命令
post-install-cmd 是常见执行点,但里面写的 cp -r、ln -sf、mkdir -p 在 Windows 上基本失效,即使用了 Git Bash 或 WSL,也容易因路径分隔符(/ vs )、换行符(LF vs CRLF)或 shell 差异导致失败。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
真正能跨平台的方案只有两条路:
- 用 PHP 写逻辑:把脚本内容放进
src/Script/PostInstallHook.php,在composer.json里声明"post-install-cmd": ["MyVendor\Script\PostInstallHook::run"]—— PHP 自带copy()、symlink()、mkdir(),且自动处理路径分隔符 - 用跨平台工具链:比如
roblocher/composer-bin-plugin或consolidation/cgr,它们内部做了 OS 判断和命令适配,不推荐手写 shell - 绝对不要在
post-install-cmd里写rm -rf或chmod—— 这些在 Windows 上无对应语义,CI 失败率极高
CI 中 vendor/bin/ 脚本权限丢失?别信 Docker 镜像默认 umask
Docker 构建时,如果基础镜像(如 php:8.2-cli)的 umask 是 0022,那 composer install 创建的 vendor/bin/* 默认只有 -rw-r--r--,没有 x 位。哪怕你在本地 chmod +x 过,Docker 构建过程会重新拉取并覆盖。
解决方案不是改镜像 umask(风险大),而是构建阶段显式补权限:
- 在
Dockerfile的composer install后加一行:RUN chmod +x vendor/bin/* 2>/dev/null || true(|| true防止某些镜像没vendor/bin目录时报错中断) - 更稳妥的是用
composer install --no-scripts,再手动触发权限修复脚本 —— 避免post-install-cmd里混入平台敏感操作 - 注意:GitHub Actions 的
ubuntu-latestrunner 默认 umask 是0002,所以权限通常没问题;但自建 runner 或私有 Kubernetes Pod 若 umask 是0022,就必须补这一环
最易被忽略的点是:权限问题往往不是孤立发生的,它常和 platform 配置、cache-dir 所有权、以及 post-install-cmd 的执行上下文(root vs non-root 用户)耦合在一起。单点修复容易反复踩坑,得连着看。










