Node.js中stdio:'inherit'与process.stdin.pipe的差异及CPU占用问题
stdio: 'inherit' Causes 100% CPU Usage vs. Using pipe in Node.js Spawn Great question—this is one of those cases where theoretical documentation equivalence doesn’t match real-world behavior, especially with interactive shell loops. Let’s break down the key differences clearly:
1. File Descriptor Sharing vs. Dedicated Pipe Communication
- When you use
stdio: 'inherit', the child shell process directly shares the exact same stdin/stdout/stderr file descriptors as your main Node.js process. For your infinitewhile :; do read a; $a; doneloop, this creates a critical conflict: the shell’sreadcommand fails to block properly when waiting for input. Instead, it keeps trying to read from the shared descriptor, gets no data, and immediately loops again—this non-stop "busy waiting" is what spikes your CPU to 100%. - When you switch to
process.stdin.pipe(child.stdin), you’re creating a dedicated pipe between the parent Node.js process’s stdin and the child’s stdin. Pipes are OS-level mechanisms designed to block when no data is available. The shell’sreadcommand will sleep until data comes through the pipe, so the CPU stays idle until input is provided.
2. Blocking Behavior Conflicts
- With
inherit, the shared stdin is tied to Node.js’s event loop. Node.js already listens for events on its own stdin, which interferes with the shell’sreadcommand. The shell can’t properly detect that no input is waiting, so it never enters a blocked state—instead, it spins through the loop non-stop. - Pipes isolate the child’s stdin from Node.js’s own stdin handling. The child process’s
readwill correctly block until data is sent through the pipe, so the shell waits peacefully instead of churning through cycles.
3. The "Equivalence" in Docs Is Only Theoretical
The Node.js docs state that 'inherit' is equivalent to [process.stdin, process.stdout, process.stderr], but this only refers to file descriptor inheritance at the OS level. In practice, when Node.js is actively managing its own stdin as a stream, sharing that descriptor with a child process running an infinite input loop causes unexpected IO handling conflicts. The pipe approach avoids this by creating a separate communication channel that doesn’t interfere with Node.js’s own stream management.
To sum it up: inherit works fine for one-off commands, but for interactive, looping shell scripts that rely on reading stdin, using a pipe is the safer choice to prevent CPU hogging.
内容的提问来源于stack exchange,提问作者bilabila

