分享我用 Wails 写一个跨平台进程管理器 ProcHub
我这台机器常年跑着几个自建服务:一个本地接口、一个定时任务,还有 WSL 里的环境。每次重启电脑,都要挨个开终端、cd 到目录、把启动命令重新敲一遍。用过的几个工具,要么只照顾某个系统,要么配置文件比服务本身还长。
折腾到后来决定自己写一个:点得开界面,命令行也能用,配置就一份。技术栈是 Wails + Go + Vue 3,做出来的东西叫 ProcHub,Apache 2.0 开源。这篇把当时的问题、做法和取舍记一下。
托管逻辑放 Go 里
每个进程就是一个结构体,配置直接落成可读的字段:
type Process struct {
ID string
Command string
Args []string
WorkDir string
Restart string // always | on_failure | never
}
启动、停止、重启走同一套流程:先起 cmd,接上 stdout 和 stderr,记下 PID。停止时先发信号让它自己收尾,超时才强杀,也就是优雅关闭。Restart 只有三档,always 崩了就拉,on_failure 只在异常退出时拉,never 不管。

开机自启交给系统
这块一开始想自己写守护进程,后来放弃了。三个平台各用各的原生机制:macOS 写 LaunchAgent 的 plist,Linux 放 XDG Autostart 的 .desktop,Windows 写注册表的 Run 项。系统启动器会在登录后把程序拉起来,不需要再多养一个进程。
设置页把这些开关集中在一处,主题、语言、开机自启和版本更新都在里面。

发布目标现在是 Windows amd64、macOS(Intel 和 Apple Silicon)、Linux amd64 / arm64。交叉编译交给 Go,前端打一次包跟着走,不用每个平台单独维护工程。
日志分两条管道
stdout 和 stderr 分开接,按行加时间戳写进滚动日志文件,保留份数可配置。同时往界面推一份实时流,点到某个进程就能看。
这里踩过坑:最早把两个流合在一起,正常输出和 panic 混在同一片里,出问题时反而更难看清。分开之后,stderr 有内容基本就说明有问题。
日志文件按进程 id 落在数据目录里,界面关掉再打开还能读,这一点排查线上问题时很省事。
CLI 和界面共用一个二进制
不额外维护一套命令行工具,程序检测到带子命令就走命令行分支,不带就开界面。
prochub process list
prochub process start api
prochub logs api --tail 200 --follow
prochub config set theme dark
prochub wsl status
prochub autostart-wsl off
WSL 单独给了几条:Windows 启不启 WSL、WSL 里的服务起没起,本来就是两件事,塞进一个开关里会互相打架。
几处取舍
- Wails 不是 Electron。这个工具大部分时间在后台待着,内存和启动速度比界面花哨更重要。代价是只能用系统 WebView,Windows 上 WebView2 版本太老会有兼容问题。
- 只做单机,不做集群。就一台开发机,加注册中心、远程控制只会让配置更重。
- 不自建守护进程。开机自启交给系统,代价是三个平台各写一份适配,换来的是不用维护一个守护自己的守护进程。
- 重启策略只留三档。够用,也解释得清;加退避、加熔断,配置复杂度立刻上一个台阶。
现在
装好之后开机不用再开终端,重启次数和最近错误在列表里一眼能看到,改设置要么点界面、要么 config set。构建需要 Go 1.23、Node 18 和 Wails CLI。
代码还在继续改,用着别扭的地方我记下来慢慢处理。如果你也有一堆开机要手动拉起的服务,说说你是怎么管的,评论区聊。
关于 LearnKu
推荐文章: