Process 是一个专为现代化云原生环境设计的 Go 进程管理库。它不仅提供了基础的进程启停功能,更深度集成了 状态机控制、拓扑依赖调度、多维健康检查、资源配额硬限制 (Linux prlimit/cgroups) 以及 RESTful 控制面板。
无论是作为微服务的 Sidecar、自研 CI/CD Agent 的核心引擎,还是需要一个比 Supervisord 更轻量、更易于嵌入 Go 应用的进程管理组件,Process 都能提供生产级的稳定性与灵活性。
ProcessBuilder API,支持流式配置,内置参数校验。prlimit 实现 CPU、内存、文件描述符的硬性配额,支持 SIGSTOP 预挂起技术防止资源逃逸。GracefulReload,通过健康检查 readiness 握手确保新老进程无缝交替。如果你只需要管理一个简单的进程,可以直接使用 NewProcess:
package main
import (
"cnb.cool/zishuo/process"
"time"
"fmt"
)
func main() {
// 创建并配置进程
proc := process.NewProcess(
process.WithName("ping-test"),
process.WithCommand("ping"),
process.WithArgs("google.com", "-c", "10"),
process.WithAutoStart(true),
)
// 启动进程(非阻塞)
proc.Start(false)
// 实时获取状态
go func() {
for {
info := proc.GetProcessInfo()
fmt.Printf("当前状态: %s, PID: %d\n", info.Statename, info.Pid)
if info.State >= 100 { // Exited or Fatal
break
}
time.Sleep(time.Second)
}
}()
// 优雅停止(阻塞直到退出)
proc.Stop(true)
}
使用 Manager 可以获得批量控制、依赖管理和更强的可观测性:
package main
import (
"cnb.cool/zishuo/process"
"log"
)
func main() {
m := process.NewManager()
// 使用链式 API 创建进程
_, err := m.Process("web-api").
Command("./server").
Args("--port=8080").
Directory("/var/www").
AutoRestart(process.AutoReStartUnexpected).
StdoutLogFile("logs/web.log").
Build()
if err != nil {
log.Fatal(err)
}
// 启动所有标记为 AutoStart 的进程(按优先级和依赖顺序)
m.StartAllProcessesInOrder(true)
// 停止所有进程
defer m.StopAllProcesses()
}
要求 Go 1.23 或更高版本。
go get cnb.cool/zishuo/process
Process 内部维护了一个严谨的状态机,确保进程行为的可预测性。
| 状态 | 值 | 说明 |
|---|---|---|
Stopped | 0 | 初始状态或已完全停止 |
Starting | 10 | 正在执行启动逻辑,尚未达到 StartSecs 判定时间 |
Running | 20 | 进程已成功运行并超过判定时间 |
Backoff | 30 | 启动失败,正在等待重试间隔 |
Stopping | 40 | 正在发送停止信号并等待退出 |
Exited | 100 | 进程自然退出(非用户手动停止) |
Fatal | 200 | 达到最大重试次数后彻底失败 |
atomic.Int32 维护进程状态,确保跨 Goroutine 读取的一致性。Start/Stop)受互斥锁保护,防止重复启动或竞态。cmdWaitDone 通道确保不会向已经彻底销毁的进程发送信号。safemap 确保在管理成百上千个进程时,并发读写 Manager 依然稳定。Process 自动探测当前操作系统的能力边界:
除了基础的 NewProcess 函数,ProcessBuilder 提供了更直观的链式配置接口,并内置了路径校验、资源限制负值检查等逻辑。
proc := process.NewProcess(
process.WithName("my-service"),
process.WithCommand("./bin/app"),
process.WithArgs("--config", "prod.yaml"),
process.WithAutoStart(true),
)
proc, err := manager.Process("worker-01").
Command("python3").
Args("worker.py").
Directory("/app/workers").
Env("REDIS_URL", "redis://localhost:6379").
Priority(10).
AutoRestart(process.AutoReStartTrue).
StdoutLogFile("logs/worker.log").
Build()
// 内部会自动处理 shell 解析逻辑
proc := process.NewProcessCmd("cd /tmp && ls -l > out.txt", nil)
wait=true,将阻塞直到进程进入 Running 状态或启动失败。基于 Kahn 算法实现,支持复杂的有向无环图 (DAG) 调度。
m.AddDependency("app", "mysql")
m.AddDependency("app", "redis")
// 启动:mysql & redis 并行启动 -> app 启动
m.StartAllProcessesInOrder(true)
// 停止:app 停止 -> mysql & redis 停止
m.StopProcessWithDependents("mysql", true)
健康检查结果存储在 O(1) 的环形缓冲区中,支持历史回溯。
func(context.Context) *HealthCheckResult。checker := process.NewHTTPHealthChecker("http://localhost:8080/health", 2*time.Second)
checker.ExpectedStatus = 200
proc.SetHealthCheck(&process.HealthCheckConfig{
Checker: checker,
Interval: 15 * time.Second,
FailThreshold: 3,
})
仅限 Linux。Process 采用了一种独特的安全启动序列:
fork 子进程。SIGSTOP 挂起自己。prlimit 设置资源限制。SIGCONT 恢复子进程。
这确保了资源限制在子进程执行任何用户代码前就已经生效。limits := &process.ResourceLimits{
MemoryLimit: 512 * 1024 * 1024, // 512MB
CPUTimeLimit: 3600, // 1小时 CPU 时间
OpenFilesLimit: 1024, // 最大文件打开数
CoreDumpSize: 0, // 禁用 Core Dump
}
支持以特定 UID/GID 运行子进程。
CAP_SETUID/CAP_SETGID。LD_PRELOAD)。logsink 包提供了工业级的日志处理能力:
// 配置标准输出到文件,50MB 切分,保留 10 个备份
process.WithStdoutLog("/var/log/app.log", "50MB", 10)
process/config 子包提供文件配置加载、保存、监听与热重载编排能力。
更完整的接入说明见 config/README.md。
import processconfig "cnb.cool/zishuo/process/config"
cm, _ := processconfig.NewManager(manager, "config.yaml", processconfig.ApplyStrategyReload)
cm.Start() // 开始监控
| 选项 | 说明 | 默认值 |
|---|---|---|
WithName | 进程唯一标识名 | 必填 |
WithCommand | 可执行文件路径 | 必填 |
WithArgs | 命令行参数列表 | 空 |
WithDirectory | 工作目录 | 当前目录 |
WithUser | 运行用户 (Linux/macOS) | 当前用户 |
WithPriority | 启动优先级 (越小越早) | 999 |
WithAutoStart | 是否随管理器启动 | true |
WithStartSecs | 判定启动成功的稳定运行时间 | 1s |
WithStartRetries | 启动失败最大重试次数 | 3 |
WithRestartPause | 重启前的等待间隔 | 0s |
WithAutoReStart | 重启策略 (true, false, unexpected) | true |
WithExitCodes | 视为正常退出的状态码列表 | [0, 2] |
WithStopSignal | 停止信号序列 | ["TERM"] |
WithStopWaitSecs | 发送信号后等待退出的时间 | 10s |
WithKillWaitSecs | 强制杀死前的最终等待时间 | 2s |
WithStopAsGroup | 是否向整个进程组发送信号 | false |
WithStdoutLog | 标准输出日志配置 (路径, 大小, 备份数) | 无 |
WithRedirectStderr | 是否将错误输出合并到标准输出 | false |
Process 提供了一个基于标准库 net/http 的 API 适配器。
| 方法 | 路径 | 说明 |
|---|---|---|
GET | /api/v1/processes | 获取所有进程列表及简要状态 |
POST | /api/v1/processes | 创建新进程 |
GET | /api/v1/processes/{name} | 获取特定进程的详细配置与运行时信息 |
POST | /api/v1/processes/{name}/start | 启动进程 (异步,返回 202) |
POST | /api/v1/processes/{name}/stop | 停止进程 |
GET | /api/v1/operations/{id} | 查询异步操作(如启动)的执行进度 |
为了防止 HTTP 请求因进程启动过慢(如 Java 应用预热)而超时,启动接口采用异步模式。返回的 operation_id 可用于轮询最终结果。
通过 GET /api/v1/processes/{name}/sse,客户端可以获得一个持久连接,实时接收:
Running -> Exited)。processes:
- name: web-server
command: ./server
args: ["--port=8080"]
directory: /var/www
autostart: true
autorestart: unexpected
exit_codes: [0, 2]
startretries: 3
startsecs: 5
stopsignal: TERM
stopwaitsecs: 10
environment:
DB_HOST: localhost
depends_on: [database]
healthcheck:
type: http
http_url: http://localhost:8080/health
interval: 10
timeout: 5
resource_limits:
memory_limit: 536870912
stdout_logfile: /var/log/app.log
stdout_logfile_maxbytes: 50MB
stdout_logfile_backups: 10
| 特性 | Linux | macOS (Darwin) | Windows |
|---|---|---|---|
| 基础生命周期 | ✅ | ✅ | ✅ |
| 资源限制 (prlimit) | ✅ | ❌ | ❌ |
| 用户切换 (Setuid) | ✅ | ✅ | ❌ |
| 进程组信号 | ✅ | ✅ | ⚠️ (有限) |
| 孤儿进程回收 (Reaper) | ✅ | ❌ | ❌ |
| 信号序列 (TERM->KILL) | ✅ | ✅ | ⚠️ (仅支持 KILL) |
WithUser 为子进程降权。HTTPHealthChecker 时,确保目标 URL 不受外部用户直接控制。Reaper 协程回收孤儿进程。SIGTERM 处理逻辑,并将 StopWaitSecs 设置为大于应用清理所需的时间。WithStartSecs 是否设置过长,或进程是否在启动后迅速崩溃。prlimit64,且当前用户有权修改 hard limit。process/config.Manager 的策略是否为 ApplyStrategyRestart。| 目录 | 演示内容 |
|---|---|
examples/lifecycle | 基础进程启停、健康检查与状态查询 |
examples/dependencies | 复杂的拓扑启动顺序演示 |
examples/healthcheck | 四种健康检查器的配置与历史记录获取 |
examples/control_httpapi | 如何集成 REST 控制面板与认证中间件 |
examples/resource_limits | Linux 下的内存与 CPU 限制实战 |
examples/sse | 实时日志推送与前端对接演示 |
examples/config_hot_reload | 配置文件监控与热重载策略 |
我们欢迎任何形式的贡献!
golangci-lint 检查,并附带必要的单元测试。本项目采用 MIT 许可证。详见 LICENSE 文件。
相关项目: