spawn
spawn 是什么
child_process 模块中的一个函数,用来
- 启动一个子进程
- 执行某个命令
- 实时捕获输出(stdout/stderr)
- 与子进程交互(通过 stdin)
spawn 适合执行需要持续交互或输出的命令,比如运行服务器、构建工具等。spawn 想成 Node 里 终端代理人
基本使用
导入
import { spawn } from 'child_process';
执行命令 node ./spawn.mjs
// spawn.mjs
const command = 'ls -la';
const cwd = process.cwd(); // 当前工作目录
const [cmd, ...args] = command.split(' ');
const child = spawn(cmd, args, {
cwd,
stdio: 'inherit', //实时输出到控制台
shell: true,
});
child.on('close', (code) => {
console.log(`子进程已结束,退出码 ${code}`);
});
-
command: 要执行的命令字符串
-
cwd: 当前工作目录
-
stdio: 'inherit' 表示子进程的输入输出与父进程共享,实时显示输出
-
shell: true 表示通过 shell 执行命令,允许使用管道等 shell 特性
-
close 事件: 当子进程结束时触发,code 是退出码
监听日志
const child = spawn('pnpm', ['dev']);
child.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
child.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
child.on('close', (code) => {
console.log(`子进程已结束,退出码 ${code}`);
});
- child.stdout.on('data'): 监听标准输出数据
- child.stderr.on('data'): 监听错误输出数据
- child.on('close'): 监听子进程结束事件
输出
stdout: > react-todo-app@0.0.1 dev
stdout: > vite
stdout: VITE v5.0.8 ready in 550 ms
stdout: ➜ Local: http://localhost:5173/
stdout: ➜ Network: http://192.168.31.88:5173/
stdout: ➜ press h to show help
错误案例输出
stderr: ✘ [ERROR] Unexpected token
stderr: src/components/TodoItem.tsx:17:14:
stderr: 17 │ return <div>{todo.title}</div>
stderr: │ ^
stderr:
stderr: 1 error
输入内容(与子进程交互(通过 stdin))
const child1 = spawn('bash', {
stdio: 'pipe',
shell: true,
});
child1.stdin.write('ls -la\n');
child1.stdin.write('pwd\n');
child1.stdin.write('echo "Hello from child process"\n');
child1.stdin.end();
child1.stdout.on('data', (data) => {
console.log(`子进程输出: ${data}`);
});
child1.stderr.on('data', (data) => {
console.error(`子进程错误输出: ${data}`);
});
child1.on('close', (code) => {
console.log(`子进程已结束,退出码 ${code}`);
});
- stdio: 'pipe' 表示父子进程通过管道通信
- child1.stdin.write(...): 向子进程的标准输入写入命令,此时 stdio: 'inherit' 不适用 , 因为需要单独操作 stdin
- child1.stdin.end(): 结束输入,告诉子进程没有更多数据了
stdio: 'inherit' 时,stdin 是继承自父进程的,不能单独写入数据,就不能再对 stdin/stdout/stderr 做手动监听或写入——包括:
child.stdin.write(...)
child.stdout.on('data')
child.stderr.on('data')
会出现如下报错
TypeError: Cannot read property 'write' of null
当使用管道符号时,必须使用 shell: true
const command =
'echo -e "n\nn" | pnpm create vite react-todo-app --template react-ts';