创建进程(Bun.spawn())
以字符串数组的形式提供命令。Bun.spawn() 的结果是一个 Bun.Subprocess 对象。
Bun.spawn 的第二个参数是一个配置子进程的参数对象。
输入流
默认情况下,子进程的输入流是未定义的;通过stdin 参数进行配置。
使用
"pipe",父进程可以增量写入子进程的输入流。
ReadableStream 传递给 stdin 会将其数据直接管道传输到子进程的输入:
输出流
从stdout 和 stderr 属性读取子进程的输出。默认情况下,它们是 ReadableStream 的实例。
stdout/stderr 传递以下值之一来配置输出流:
退出处理
使用onExit 回调监听进程退出或被杀死的事件。
index.ts
exited 属性是一个 Promise,在进程退出时 resolve。
index.ts
index.ts
bun 进程在所有子进程退出后才会终止。使用 proc.unref() 将子进程与父进程分离。
index.ts
资源使用
进程退出后,resourceUsage() 会报告其资源使用情况:
index.ts
使用 AbortSignal
您可以使用AbortSignal 中止子进程:
index.ts
使用 timeout 和 killSignal
设置timeout 可以在指定毫秒数后终止子进程:
index.ts
SIGTERM 杀死超时进程。使用 killSignal 选项指定不同的信号:
index.ts
killSignal 选项还控制在 AbortSignal 被中止时发送的信号。
使用 maxBuffer
对于Bun.spawnSync,maxBuffer 限制进程在 Bun 杀死它之前可以发出的输出字节数:
index.ts
maxBuffer 一个读取的量,而不会超过进程在杀死信号到达之前设法写入的量。这与 Node.js 的行为一致。
进程间通信(IPC)
Bun 支持两个bun 进程之间的直接进程间通信通道。要从生成的 Bun 子进程接收消息,请指定一个 ipc 处理器。
parent.ts
Subprocess 实例上的 .send() 方法向子进程发送消息。ipc 处理器也会接收发送消息的子进程作为其第二个参数。
parent.ts
process.send() 向父进程发送消息,并使用 process.on("message") 接收消息。这与 Node.js 中 child_process.fork() 使用的 API 相同。
child.ts
child.ts
serialization 选项控制两个进程之间的底层通信格式:
advanced:(默认)消息使用 JSCserializeAPI 进行序列化,支持克隆structuredClone支持的一切。不支持传输对象所有权。json:消息使用JSON.stringify和JSON.parse进行序列化,不支持advanced那么多对象类型。
Bun 与 Node.js 之间的 IPC
要在bun 进程和 Node.js 进程之间使用 IPC,请在 Bun.spawn 中设置 serialization: "json"。这是因为 Node.js 和 Bun 使用不同的 JavaScript 引擎和不同的对象序列化格式。
bun-node-ipc.js
终端(PTY)支持
对于交互式终端应用程序,请使用terminal 选项来生成附加了伪终端(PTY)的子进程。子进程会看到一个真正的终端,从而支持彩色输出、光标移动和交互式提示。
terminal 选项时:
- 子进程看到
process.stdout.isTTY为true stdin、stdout和stderr都连接到终端proc.stdin、proc.stdout和proc.stderr返回null— 请改用终端- 通过
proc.terminal访问终端
终端选项
终端方法
proc.terminal 返回的 Terminal 对象有以下方法:
可复用终端
要在同一个终端会话中顺序运行多个命令,可以独立创建一个终端并在多个子进程之间复用:Terminal 对象时:
- 终端可以在多次 spawn 中复用
- 您可以控制何时关闭终端
exit回调在调用terminal.close()时触发,而不是在每个子进程退出时- 使用
proc.exited检测单个子进程的退出
平台差异
Bun.Terminal 在 Linux 和 macOS 上使用 openpty(),在 Windows 上使用 ConPTY(CreatePseudoConsole)。核心行为——子进程看到 TTY、write() 到达子进程的 stdin、子进程输出到达 data 回调、resize() 更新子进程的视图——在所有平台上都是相同的。一些细节有所不同:
- Windows 上没有 termios。
inputFlags、outputFlags、localFlags和controlFlags始终读取为0,设置它们无效。setRawMode()会记录该标志但对子进程没有效果;子进程控制自己的控制台模式。 - Windows 上没有子进程时不会回显。 在 POSIX 上,即使没有附加进程,内核的行规程也会将
write()输入回显到data回调。ConPTY 没有行规程;输入会被缓冲等待下一个读取者。如果需要回显,请启动一个会回显的进程。 - ConPTY 会重新编码输出。 ConPTY 将子进程的输出渲染到虚拟屏幕,并发出描述结果的任何 VT 序列,因此
data回调接收的转义序列在语义上等价,但字节不一定相同。颜色和文本被保留;光标定位和重置序列可能会被重新排序或合并。ConPTY 还会在任何子进程输出之前发出一个简短的 VT 初始化序列(\x1b[?9001h\x1b[?1004h…)。 - 在 Windows 上,输入的
\r不会转换为\n。 POSIXICRNL会将回车符映射为输入中的换行符;ConPTY 原样传递\r。 - 在 ConPTY 下,子进程中的
process.on('SIGWINCH')不会触发,除非子进程以原始模式读取 stdin。process.stdout.columns/rows在resize()后确实会更新。这是 libuv 的限制,影响所有基于 libuv 的子进程(包括 Node.js)。 - 在 Windows 11 24H2(内部版本 26100)之前的版本上,
terminal.close()可能不会及时终止仍在运行的子进程,因为在这些版本上ClosePseudoConsole会阻塞直到 conhost 将其输出通过管道刷新完毕。如果需要在子进程仍在运行时销毁,请先杀死附加的进程。
阻塞 API(Bun.spawnSync())
Bun.spawnSync 是 Bun.spawn 的阻塞等价物。它支持相同的输入和参数,并返回一个 SyncSubprocess 对象,该对象在几个方面与 Subprocess 不同。
- 它包含一个
success属性,指示进程是否以零退出代码退出。 stdout和stderr属性是Buffer的实例,而不是ReadableStream。- 没有
stdin属性。请使用Bun.spawn来增量写入子进程的输入流。
Bun.spawn API 更适合 HTTP 服务器和应用程序,而 Bun.spawnSync 更适合构建命令行工具。
基准测试
⚡️
Bun.spawn 和 Bun.spawnSync 使用 posix_spawn(3)。spawnSync 创建进程的速度比 Node.js child_process 模块快 60%。
terminal
terminal
参考
以下是 Spawn API 和类型的参考。实际类型具有复杂的泛型,可以根据传递给Bun.spawn 和 Bun.spawnSync 的选项强类型化 Subprocess 流。有关完整细节,请参阅 bun.d.ts。
查看 TypeScript 定义 可展开