composer脚本中read或echo无反应,是因为其默认不透传stdin且不保证tty交互环境,ci等非交互场景下read立即读到eof,echo则不阻断执行;可靠方案是将交互逻辑移至独立shell脚本(如bin/setup-dev),用[ -t 0 ]判断tty并调用bash原生命令,再通过composer.json中"setup-dev": "bash bin/setup-dev"调用。

Composer脚本里直接写read或echo为什么没反应
因为Composer执行scripts时默认不透传STDIN,也不保证终端处于交互模式。哪怕你写了read -p "确认?" ans,在CI、SSH非登录shell或GitLab Runner里也会立刻读到EOF,表现为“一闪而过、无停顿、直接往下走”。echo单独一行更没用——它只是输出,不阻断执行流。
真正起作用的交互必须绑定到有阻断能力的操作上,且得让shell自己处理stdin,不能依赖PHP层或Composer封装。
- 别在PHP脚本里调用
fgets(STDIN)或readline():非TTY环境下必然失败 - 别把提示和动作拆成两条scripts命令:Composer不会等你回车再跑下一条
- Windows下
read根本不存在,得用set /p或统一走cross-env - 检查是否真有TTY:
[ -t 0 ] && echo "ok" || echo "skip",非交互环境必须自动跳过提示
怎么让composer run-script setup-dev真正停下来等用户输入
唯一可靠的方式是绕过Composer对stdin的屏蔽,把交互逻辑完全交给独立shell脚本控制。
例如,在bin/setup-dev里写:
#!/usr/bin/env bash
if [ -t 0 ]; then
read -p "⚠️ 将重置本地数据库,继续?(y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[yY]$ ]]; then
exit 1
fi
else
echo "非交互环境,跳过确认"
fi
php artisan migrate:fresh --seed
然后在composer.json中定义:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
"scripts": {
"setup-dev": "bash bin/setup-dev"
}
- 脚本开头必须
#!/usr/bin/env bash,避免系统默认sh不支持read -n -
bash bin/setup-dev比php bin/setup-dev更可控,因为bash原生支持完整交互语义 - 不要用
exec前缀或sh -c包裹交互命令:它们不继承父进程的tty状态 - CI中可加
export CI=true,并在脚本里用[ -z "$CI" ] && [ -t 0 ]双重判断
复杂安装脚本该用shell还是PHP写
优先用PHP写主逻辑,但把交互、路径探测、环境判别这类系统级操作留给shell包装器。
比如scripts/install.php负责校验扩展、生成配置、调用composer require;而bin/install只做三件事:确认TTY、显示banner、决定是否跳过某些步骤。
- PHP脚本必须显式
require __DIR__.'/../vendor/autoload.php',否则Class not found - 所有传给PHP脚本的参数必须用
--分隔:composer run install -- --env=prod - 批量
composer require务必加--no-update,最后统一composer update --no-interaction - 避免在scripts里拼长shell链如
php a.php && php b.php && npm run build:一处失败就中断,无法捕获错误码
部署脚本里composer install卡住的根本原因
不是缺--quiet,而是没加--no-interaction(简写-n)。很多包的post-install-cmd会主动触发交互提示,比如Symfony Flex问“是否启用recipe”,Laravel Installer问“是否生成.env”。
即使你自己的scripts没写交互,第三方包也可能有。
- CI/CD中固定用:
composer install -n --optimize-autoloader --no-dev -
--no-interaction必须显式传,COMPOSER_NO_INTERACTION=1环境变量不可靠 - 如果脚本里要多次调用
composer命令,每次都要带-n,不能只在最外层加 - PHP平台配置不一致(如CI用8.3,本地用8.2)可能触发warning并意外拉起交互,需提前用
platform字段锁死
实际落地时最容易被忽略的是:交互逻辑和主逻辑必须物理分离。把read塞进PHP里,或者指望composer run -v就能唤醒stdin,都是徒劳。真正的控制权在shell层,PHP只管做事。










