为什么我停止使用 PM2 并自行构建了 Bun 进程管理器
Source: Dev.to
我曾经很喜欢 PM2。后来我转向了 Bun。
六个月前,我把少量微服务从 Node 迁移到了 Bun。速度提升符合基准测试:冷启动时间大幅下降,内存占用也缩小了。我非常激动——直到我意识到我的进程管理器 PM2 成了整个栈中最慢的部分,且经常消耗最多的内存。用基于 Node 的监控器去管理高度优化的 Bun 进程显得有些讽刺,于是我利用周末时间构建了一个替代品。
致命点
导致我放弃的并不是单一问题,而是一连串小摩擦:
- PM2 有时会错误报告 Bun 进程的内存使用情况。
- TypeScript 集成需要额外的标志和变通办法。
- 维护单独的
ecosystem.json与我的 Bun 原生工具链显得格格不入。 - 每次执行
pm2 start时,都要等 Node 守护进程启动后才会启动 Bun 进程,延迟明显。
在记录这些摩擦点几周后,清单已经足够长,足以支撑一个项目的动机。
我做了什么
BM2 是一个只做一件事的进程管理器:在不依赖任何 Node 的情况下管理长期运行的 Bun 进程。
- 没有在其他运行时上运行的守护进程。
- 没有兼容层——只有 Bun 管理 Bun。
- 熟悉的 CLI 语法。
npm i -g bm2
bm2 start server.ts --name api
bm2 restart api
bm2 logs api --lines 100
bm2 list
在内部,一切都使用 Bun 的原生 API:
- 通过
Bun.spawn创建子进程。 - 通过
Bun.write与Bun.file进行文件操作。 - 状态信息存储在 Bun 内置的 SQLite 中。
没有 fs 填充,没有 Node 的 child_process——纯 Bun。
结果
将服务从 PM2 迁移到 BM2 后,我观察到:
- 进程管理器几乎瞬间启动——没有守护进程的启动延迟。
- 内存开销显著下降,因为管理器不再与 Bun 并行运行完整的 Node 运行时。
- TypeScript 文件开箱即用——无需额外标志、配置或转译。
- 整个栈现在只运行在单一运行时上,提供了统一的开发者体验。
你该不该切换?
如果你仍在运行 Node 服务,PM2 仍是一个优秀、成熟、经过实战检验的解决方案。
然而,如果你已经决定使用 Bun——包括运行时、包管理器、测试运行器——就需要考虑你的工具链是否已经跟上。既然其他一切都已经是 Bun,何必再保留基于 Node 的进程管理器?
正是这个问题促使我构建了 BM2。它也许正是你一直在忽视的问题。
链接
- 代码仓库:
- 包: