Node CLI运行长时子进程时按键隔个丢失问题排查与解决
Node CLI启动子进程后按键输入丢失(隔一个才读取)的问题排查与解决
问题成因
核心原因是启动子进程时,子进程默认会继承父进程的标准输入(stdin)。当你在父进程中开启raw mode监听stdin时,子进程(比如你的Gradle watch进程)也会同时读取这份输入流,导致按键事件被父、子进程分流——父进程拿到一个按键,子进程吃掉下一个,最终表现为“每隔一个按键才能被父进程读取”。
Gradle watch模式本身会默认监听终端输入流,即使它看起来没用到这个能力,也会和Node父进程争抢stdin的数据。
解决方法
关键是禁止子进程继承父进程的stdin,将子进程的stdin重定向到空,让它无法读取终端输入,从而让父进程独占stdin的控制权。
具体实现(以child_process.spawn为例)
假设你用spawn启动Gradle子进程,修改子进程的stdio配置:
const { spawn } = require('child_process'); // 启动Gradle时,将stdin设置为ignore/null,避免抢父进程的输入 const gradleProcess = spawn('./gradlew', ['watch'], { stdio: ['ignore', 'inherit', 'inherit'] // stdin忽略,stdout/stderr继承父进程(正常输出日志) // 等价写法:stdio: [null, process.stdout, process.stderr] });
配置说明
stdio数组的三个元素分别对应子进程的stdin、stdout、stderr:
- 设为
'ignore'或null:子进程不继承父进程的对应流,直接丢弃输入,彻底避免和父进程抢stdin - 设为
'inherit':子进程继承父进程的对应流,保证Gradle的日志能正常输出到终端
如果你的场景需要子进程和父进程共享stdin(比如复杂交互场景),需要做流转发逻辑,但你的场景是父进程独占按键控制,直接忽略子进程stdin即可。
验证效果
修改后,父进程的stdin事件会正常捕获每一次按键输入,不会再出现丢失,同时Gradle watch模式也能正常运行(它本身不需要读取终端输入)。
内容的提问来源于stack exchange,提问作者Jarek
相关产品推荐
相关产品推荐

