跨平台脚本需显式指定解释器并拆分逻辑:linux/macos用sh -c,windows用cmd /c;工具路径统一用./vendor/bin/xxx;复杂逻辑改用php脚本实现。

能调用,但直接写 ls、rm -rf 或 echo hello && php -v 会立刻在 Windows 上失败。跨平台脚本不是“让命令自动适配”,而是你主动绕过 shell 差异。
为什么 sh -c 和 cmd /c 是唯一可靠入口
Composer 的 scripts 字段不解析命令语法,它只是把字符串原样交给系统 shell 执行。Linux/macOS 默认用 bash 或 sh,Windows 默认是 cmd.exe,二者对管道、转义、空格、逻辑运算符的支持完全不同。
- 写
"find ./src | xargs php-cs-fixer fix":Linux 可跑,Windows 直接报'find' is not recognized - 写
"echo hello && php -v":Windows 的&&需要转义为^&^&,否则只执行前半句 - 写
sh -c "find ./src | xargs php-cs-fixer fix":Linux/macOS 成功;Windows 报错,因为没sh - 写
cmd /c "echo hello ^&^& php -v":Windows 成功;Linux 报错,因为没cmd
所以必须显式指定解释器,并按平台拆分逻辑——要么用两个 script,要么在 PHP 脚本里做判断。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
用 ./vendor/bin/xxx 调用工具比裸命令名更稳
很多教程教你在 scripts 里直接写 phpunit 或 php-cs-fixer,但这依赖 $PATH 包含 vendor/bin。CI 环境、Docker、非交互式 shell 下,$PATH 往往不包含它,结果就是 command not found。
- 错误写法:
"test": "phpunit --testsuite unit" - 正确写法:
"test": "./vendor/bin/phpunit --testsuite unit" - Windows 下
./vendor/bin/phpunit实际调用的是phpunit.bat,Linux 下是 shell 脚本,Composer 自动匹配,无需判断系统 - 该写法不依赖
$PATH,也不需要bin-compat=full配置,所有环境开箱即用
复杂逻辑别硬塞 shell,改用 PHP 脚本回调
一旦脚本里出现条件判断(比如“如果文件存在才执行”)、循环、错误捕获或跨平台路径拼接,shell 就迅速失控。PHP 脚本可读性高、调试方便、环境可控,且天然跨平台。
- 不要写:
"pre-build": "if [ -f .env ]; then echo 'env exists'; fi"(Windows 不认[) - 改写为 PHP 脚本:
"pre-build": "php build-check.php" -
build-check.php开头加#!/usr/bin/env php并chmod +x,或直接用php build-check.php调用 - 在脚本里用
file_exists(__DIR__ . '/.env')判断,比 shell 更准;用exec()时显式传['PATH' => $_SERVER['PATH']]控制环境 - 别在脚本里用
die(),用exit(1)显式返回错误码,否则 Composer 会静默失败
真正难的不是写对一个命令,而是确保它在 CI 的 Ubuntu 容器、同事的 macOS、你自己的 Windows WSL 里都输出一致结果。路径用 /、工具用 ./vendor/bin/xxx、逻辑用 PHP 回调——这三件事做完,90% 的跨平台脚本问题就消失了。










