Composer脚本中裸写shell命令会失败,因Composer将其当作PHP文件调用;须用exec前缀或sh -c包裹,前者仅执行单命令,后者支持完整shell特性;Windows下需用cmd /c替代sh -c。

Composer脚本里直接写shell命令会失败?
默认情况下,composer.json 中的 scripts 字段不支持裸写 shell 命令(比如 "php -v" 或 "ls -la"),因为 Composer 会尝试把整个字符串当作 PHP 可执行文件去调用,报错类似:Could not open input file: php -v。
必须显式声明执行器类型,否则命令根本不会进 shell。
- 用
exec前缀:例如"exec php -v"—— 这是 Composer 内置的快捷方式,等价于调用系统exec()函数 - 用
sh -c包裹:例如"sh -c 'php -v && echo ok'"—— 更灵活,支持管道、分号、变量扩展 - 避免写成
"php -v"单独一行,它会被当成 PHP 脚本路径处理
为什么 exec 和 sh -c 行为不一样?
exec 是 Composer 的语法糖,底层调用 PHP 的 exec() 函数,只执行**单条命令**,不支持 shell 特性(如 &&、|、$PATH 变量、通配符)。而 sh -c 真正启动一个 shell 进程,完整继承当前环境。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
"exec ls *.php"→ 不展开*,字面匹配文件名*.php -
"sh -c 'ls *.php'"→ 正常 glob 展开,列出所有.php文件 -
"exec git status && git add ."→ 报错,&&不被识别 -
"sh -c 'git status && git add .'"→ 正常执行,支持逻辑连接
Windows 下运行 shell 命令要注意什么?
Composer 在 Windows 上默认调用 cmd.exe,不是 bash。所以 sh -c 会失败(除非你装了 Git Bash 或 WSL 并配置了 SHELL 环境变量)。
- 跨平台兼容写法优先用
exec+ 单命令,比如"exec php artisan optimize" - 若必须用复合命令,改用
cmd /c:例如"cmd /c \"echo hello ^&^& php -v\""(注意&需转义) - 检查
$_SERVER['OS']或PHP_OS_FAMILY在自定义 PHP 脚本中做分支,比硬写 shell 更可靠
脚本中获取当前项目路径或环境变量安全吗?
Composer 执行脚本时,工作目录(getcwd())是项目根目录,这点可靠。但环境变量如 APP_ENV、PATH 取决于执行 composer 的上下文——CI 环境可能没加载用户 shell 配置,~/.bashrc 里的 export 不生效。
- 不要依赖未显式设置的环境变量,比如假设
npm在PATH里;用绝对路径或先检测:"sh -c 'command -v npm >/dev/null 2>&1 && npm run build || echo \"npm missing\"'" - 项目路径可用
%CURRENT_DIR%(Composer 2.2+ 支持的占位符),但旧版本不识别,稳妥做法是在 PHP 脚本中用__DIR__ - 敏感操作(如
rm -rf)务必加-i或先echo预览,脚本一旦写错可能误删 vendor
真正麻烦的不是怎么写命令,而是不同平台下 shell 解析逻辑、环境变量加载时机、glob 行为差异这些隐性约束。别图省事省掉 sh -c 或 exec 前缀,也别在脚本里硬编码路径假设用户装了某工具。

















