← 返回全部文章

终端窗口开一排?Kranz 把本地服务统一管起来

前端、API、Worker 和模拟服务分散在多个终端,Kranz 用一份 YAML 管理启动顺序、健康检查、日志、端口冲突、重启和统一退出。这里给出一个可运行的三服务示例,也讲清它和 tmux、脚本、Docker Compose 的边界。

一个稍微复杂点的项目,开工仪式通常很固定:先开数据库代理,再开 API 、前端和 Worker,最后补上消息消费者或模拟服务。每个命令占一个终端标签页,启动顺序靠记,日志出错时再挨个找窗口。

关项目也不省心。主进程收到了 Ctrl+C,它拉起的子进程可能还留在后台;第二天重启,才发现昨天的服务仍占着 30008080 端口。

Kranz 把这些本地开发进程收进一份 YAML 和一个终端界面。它可以按依赖条件启动服务,分别检查 readiness 与 liveness,集中显示日志,发现端口占用,也能按顺序停止依赖链。

这个项目刚创建一周,当前稳定版是 v0.3.0。功能做得很密,但成熟度还需要时间验证。它目前面向 macOS 和 Linux,Release 提供两套系统的 x86_64 与 arm64 压缩包,没有 Windows 版本。

项目地址:github.com/kranz-org/kranz

Kranz 管的是本地开发进程

Kranz 的定位很窄,也很实用:开发者已经知道项目要运行哪些命令,它负责把命令按顺序拉起来,并持续展示状态。

它能管理:

  • npm 、 bun 、 Go 、 Python 等直接运行在宿主机上的开发命令;
  • 服务之间的启动依赖和健康状态;
  • 自动重启、退避时间与重启上限;
  • 端口冲突、监听地址和进程 PID;
  • 内存中的集中日志、过滤、高亮、暂停和未读计数;
  • 按标签分组启动前端、后端或核心服务;
  • 配置文件与 .env 变化后的热重载。

它没有提供远程控制、生产守护、水平扩缩容、定时任务、持久化日志平台或交互式提权执行。服务器部署继续用 systemd 、 Kubernetes 、 Docker Compose 或现有发布平台。

安装 v0.3.0

macOS 或 Linux 已安装 Homebrew 时,直接执行:

brew install kranz-org/tap/kranz

有 Go 1.24 及以上环境,也可以安装最新公开版本:

go install github.com/kranz-org/kranz/cmd/kranz@latest
kranz --version

Linux x86_64 想直接使用 Release 二进制,可以下载压缩包和校验文件:

curl -LO https://github.com/kranz-org/kranz/releases/download/v0.3.0/kranz_0.3.0_Linux_x86_64.tar.gz
curl -LO https://github.com/kranz-org/kranz/releases/download/v0.3.0/checksums.txt

sha256sum -c checksums.txt --ignore-missing
tar -xzf kranz_0.3.0_Linux_x86_64.tar.gz

mkdir -p ~/.local/bin
install -m 0755 kranz ~/.local/bin/kranz
kranz --version

官方 checksums.txt 中,这个压缩包的 SHA-256 是:

eccbaad3e369b9101b48d74cd4b0311d6aa1f819924e72cb2742f610ddb5464c

版本更新后,文件名和哈希都会变化,按对应 Release 页面重新核对。

三个服务,先跑通最小配置

在项目根目录创建 kranz.yaml。下面的示例包含一个 API 、一个前端和一个 Worker:

project: LocalDemo
version: "1.0"

defaults:
  dir: .
  shell: /bin/bash
  env_files: [.env.shared]

services:
  api:
    command: bun run --watch src/main.ts
    ports: [3801]
    tags: [backend, core]
    healthcheck:
      readiness:
        type: http
        url: http://127.0.0.1:3801/ready
        interval: 2s
        timeout: 1s
    availability:
      restart: on_failure
      backoff: 2s
      max_restarts: 5

  web:
    command: npm run dev
    dir: apps/web
    ports: [3000]
    tags: [frontend]
    depends_on: [api]
    dependency_conditions:
      api:
        condition: process_healthy

  worker:
    command: python -m app.worker
    dir: services/worker
    tags: [backend]
    depends_on: [api]
    dependency_conditions:
      api:
        condition: process_healthy

这份配置里,api 先启动。只有 http://127.0.0.1:3801/ready 通过检查,webworker 才会继续运行。 API 启动了却还没完成数据库连接时,后面的服务不会抢跑。

在配置目录执行:

kranz

也可以显式指定文件,或把团队配置和个人覆盖层合并:

kranz path/to/kranz.yaml
kranz -f kranz.yaml -f kranz.local.yaml

多个 -f 文件按从左到右合并。 Kranz 默认依次查找 kranz.yamlkranz.ymlprocess-compose.yamlprocess-compose.yml

第一次进入界面怎么操作

几个按键已经能完成日常工作:

1 / 2 / 3   聚焦服务、详情、日志
Space       选择服务
s           按依赖关系启动或停止
Shift+S     只操作当前目标,忽略依赖扩展
r           重启当前服务
a           全选或清空选择
A           停止全部服务
/           正则过滤日志
f           暂停或继续跟随日志
q           有序停止全部进程并退出
Ctrl+C      立即停止全部进程并退出
?           打开帮助

选择全部服务后按 s,Kranz 会先启动依赖项。等待健康检查的服务显示为 queued,详情区域会写清它在等谁。停止后端时,它会先反向停止依赖这个后端的前端和 Worker 。

我用 v0.3.0 在 Linux 上跑了一组临时服务:一个 Python HTTP API,两个依赖 API 健康状态的长运行进程。 API 返回 200 后,另外两个进程才启动;按 Ctrl+C 退出后,三个子进程全部清理,测试端口也关闭了。

这只是最小功能验证,不代表大型项目、不同 Shell 和各种子进程都不会出问题。正式接入自己的仓库前,先用无副作用命令测试启动和退出。

日志终于不再散在多个标签页

Kranz 的右侧面板显示当前服务输出,支持固定一个服务的日志,再切到另一个服务比较。日志可以正则过滤或高亮,长行可以换行,也能暂停跟随。

日志保存在有界内存缓冲区里。它不读取磁盘日志,也不是长期日志系统。需要跨天检索、告警和审计时,仍要接 Loki 、 ELK 、 Cloud Logging 或项目已有设施。

子进程输出中的终端控制序列会被清理,避免某个服务清屏或移动 Kranz 界面。时间戳是 Kranz 捕获日志时添加的元数据,不会混进正则搜索文本。

依赖条件不止“进程已经启动”

Kranz 支持五种依赖条件:

process_started
process_healthy
process_completed
process_completed_successfully
process_log_ready

process_started 只确认进程已创建;process_healthy 等 readiness 通过;process_completed_successfully 适合一次性迁移脚本成功后再启动 API;process_log_ready 可以等待某行日志出现。

健康检查支持 HTTP 、 TCP 和命令三种类型。 readiness 控制依赖放行,liveness 用于判断运行中的服务是否还健康。两者需要分别配置,空的 healthcheck 会被拒绝。

端口冲突能看到“谁占着”

配置中的端口已经被占用时,Kranz 会区分两种情况:

  • 端口属于另一个 Kranz 管理的服务;
  • 端口属于外部进程,并显示 PID 和进程信息。

对外部进程,界面可以在明确确认后发送终止信号并重试。执行前它会再次扫描端口,如果 PID 已变化或端口已经归 Kranz 管理,就拒绝终止动作;先发 SIGTERM,超过宽限期才升级。

这层保护降低了误杀概率,但不能替代判断。数据库、代理、 VPN 或其他项目也可能占着同一个端口,按下确认前先看清进程路径和命令。

配置改了,不必整套重启

Kranz 会监视配置与环境文件。合法修改会自动协调运行状态;YAML 写坏时继续保留上一份可用配置。Ctrl+L 可以立即重载。

.envdefaults.env_files 和每个服务自己的 env_files 都能使用。服务里直接写的环境变量优先级最高。

环境文件常放数据库密码和 API Key 。 Kranz 会读取这些文件并把值传给子进程,因此只运行可信仓库里的配置。日志如果主动打印环境变量,敏感值仍会出现在终端;Kranz 不会替项目自动脱敏。

和常见方案怎么选

Shell 脚本或 concurrently

服务少、没有健康检查时,一条脚本最轻。服务增加后,状态、依赖、日志过滤和有序关闭需要自己补。

tmux 或一排终端标签页

tmux 很灵活,适合高度定制的个人工作流。 Kranz 提供的是一份可以提交到仓库的服务定义,新成员不用重新学习每个人的窗口布局。

Docker Compose

Docker Compose 管容器、网络、卷和镜像。 Kranz 更适合直接运行在宿主机上的开发命令,也可以把某个 Compose 命令当作普通服务启动。它不会替代容器隔离和镜像构建。

Process Compose

Kranz 能读取 Process Compose 的常用安全子集,包括命令、依赖、健康检查、环境、重启和关闭策略。副本数大于 1 、定时任务、 daemon 、 TTY 、交互与前台模式会被明确拒绝,文件日志配置会提示忽略。

用之前要知道的边界

Kranz 的 YAML 可以执行任意本地命令。克隆陌生仓库后不要直接运行里面的配置,先逐条看清 commandshutdown.command 和环境文件。

Ctrl+O 可以暂时交出终端控制权并打开 Shell,托管服务继续运行。这个功能适合临时执行迁移或测试,也意味着 Kranz 无法给这些命令提供沙箱。

项目于 2026 年 7 月 21 日创建,一周内发布到 v0.3.0。 Release 包带独立校验文件,仓库有 CI 、测试和安全报告入口;快速迭代也会带来配置与交互变化。团队采用时锁定版本,把 kranz.yaml 跟代码一起评审,升级前先看 Changelog 。

本地项目只有一个服务时,Kranz 增加的配置不划算。前端、 API 、 Worker 、代理和模拟服务已经排成一列时,它能把每天重复的启动、等候、看日志和收尾动作收进同一个终端界面。

你现在开一个项目,通常要同时摆几个终端窗口?

来源:https://github.com/kranz-org/kranz