
今天给大家分享一个我写的工具,bm2,一个用 MoonBit 实现的 pm2 替代品。
仓库地址:https://github.com/chenbimo/bm2。
有人可能要纳闷了,pm2 用得好好的,为啥要替代?
提示:时间有限,当前工具还没提供在线安装,更新,讨论交流请于文末联系。
为啥要替代 pm2?
pm2 是 Node 生态的老牌进程管理工具,确实好用。
但我日常使用的命令只有几个,pm2的命令有几十个,90%的功能我用不上。
所以我就想,能不能自己写一个更轻、更简单的?
于是,bm2 就诞生了。
bm2 是啥?
一句话:bm2 是 pm2 的替代品,专门用来在 linux 系统环境下管理 Nodejs 和 Bunjs 运行的项目。
它用 MoonBit 语言编写,整个工具就两个文件,拿到就能用。
用起来有多简单呢?
先写一个配置文件,告诉它你的应用在哪:
# bm2.toml
[[apps]]
name = "api"
cwd = "/srv/api"
script = "index.ts"
instances = 2
base_port = 3000
然后一条命令启动:
bm2 start
完事了。
它有多轻?
这是我本机真实测量的结果:
| 项目 | 数据 |
|---|---|
| bm2 程序体积 | 2.8 MB |
| 后台服务体积 | 3.0 MB |
| 常驻内存 | 2.7 MB |
| 命令响应 | 3 毫秒 |
就一个字:轻。
后台服务长期跑着,内存占用不到 3 兆,比一个网页还轻。
命令响应 3 毫秒,感觉不到任何延迟。
它能干哪些活?
- 自动重启:应用崩了,它马上帮你拉起来,不用你半夜爬起来看日志。
- 内存保护:应用内存超了,它自动处理,不会让一个坏应用拖垮整台机器。
- 多实例运行:一个应用开好几个实例,端口自动分配,模拟线上环境很方便。
- 状态查看:应用是死是活、占了多少内存、跑了多久,一条命令全部看得到:
- 一键停止:不想跑了,一条命令全部停掉:
- 手滑保护:停掉全部应用这种危险操作,它还会让你先确认一下。
- 更新不中断:后台服务要升级?一条命令搞定,你的应用全程不用停机。
bm2 与 pm2 对比
聊进程管理,得先说清楚一个东西:进程模式。
pm2 跑应用有两种模式。
一种是 fork 模式,每个实例都是一个完全独立的进程,各干各的。
就像银行开了几个独立窗口,每个窗口自己排队,互不知道对方的存在。
一种是 cluster 模式,利用 Node.js 自带的 node:cluster 模块,一个主进程监听端口,再把请求分发给各个工作进程。
就像银行有了一台总叫号机,客户进门先取号,叫号机把客户平均分到各个窗口。
听起来 cluster 模式更高级对吧?
但它有个硬限制:node:cluster 是 Node.js 专属的能力。
也就是说,pm2 的 cluster 模式只对 Node.js 项目有效。
假如你的项目是用 Bun 跑的,pm2 只能退回 fork 模式。
而 fork 模式下,多个实例没法监听同一个端口,端口分配得应用自己想办法。
bm2 在这里做了一个直接的选择:只用 fork 模式,把负载均衡交给专业的工具。
bm2 会基于 base_port 和 instances,给每个实例自动分配端口。
第一个实例用 3000,第二个用 3001,以此类推,不用你操心。
然后在前面的 nginx 或 caddy 里配一个 upstream,把流量平均分到这些端口上。
对齐一下,两边是这样的:
| 维度 | pm2 | bm2 |
|---|---|---|
| 进程模式 | fork 和 cluster 两种 | 只有 fork |
| 端口分配 | cluster 共享端口,fork 应用自管 | base_port 起步,实例递增,自动分配 |
| 负载均衡 | cluster 模式内置内核级分发 | 交给 nginx / caddy |
| Node.js 项目 | 两种模式都支持 | 支持 |
| Bun 项目 | 只能 fork 模式 | 支持 |
| 实例编号 | NODE_APP_INSTANCE | BM2_APP_INSTANCE,约定一致 |
这两种方式没有谁好谁坏,定位不同而已。
cluster 模式的好处是不用装别的工具,单机直接扛流量。
bm2 的方式,多实例天然跨运行时,Node.js 和 Bun 一视同仁。
而且说实话,真实的线上环境,前面本来就有 nginx 或 caddy 做反向代理。
bm2 的多端口方案,正好和线上架构接上,负载均衡这一层是现成的。
对独立开发者来说,少一层内置功能,就少一份维护成本。
为啥用 MoonBit 写?


MoonBit 是一门比较新的编程语言,语法非常简洁。
有多简洁呢?看一个例子:
fn main {
println("Hello, bm2!")
}
它的好处,正好对应了上面那些数据。
- 程序小:MoonBit 编译出来的二进制非常紧凑,所以 bm2 只有 2.8 兆。
- 跑得快:编译成机器码直接运行,所以命令响应只要 3 毫秒。
- 省内存:没有运行时拖累,所以常驻内存只有 2.7 兆。
- 语法简单:我写起来很舒服,加功能、修 bug 都很快,bm2 才能持续打磨。
说实话,用 MoonBit 写这种系统级的小工具,是非常合适的搭配。
而且 MoonBit 生态也在慢慢长大,包管理、构建工具都挺齐全,写工具的门槛越来越低。
MoonBit官网 https://www.moonbitlang.cn/
写在最后
如果你也在找 pm2 的替代品,想要一个更轻、更简单、更省心的进程管理工具,不妨试试 bm2。
它是用 MoonBit 写的,这是 MoonBit 在系统工具领域的一个真实落地。
如果本文对你有帮助,欢迎一键三连,给我一些支持和鼓励,谢谢。
不知道你怎么看呢?欢迎在评论区留言。
