Skip to content

状态与日志 ​

状态目录在哪 ​

当前 Linux 用户的 ~/.bm2。HOME 不可用时回退到 /tmp/bm2-<uid>。每个用户一个守护进程,管理全部已注册项目。

这个路径是固定的,配置无法改变它:bm2 按 Linux 用户划分管理范围,而一个可以被指到别处的守护进程,会心安理得地把同一批应用管上两遍。

目录布局 ​

text
daemon.endpoint                     # 控制通道端点:本机端口 + 共享令牌(目录权限 0700)
bm2d.lock                           # 同一时刻只有一个守护进程;持有者退出即释放,SIGKILL 也不例外
bm2d.pid                            # 守护进程 PID
bm2.events.jsonl                    # CLI 连接与重试事件
bm2d.log                            # 守护进程 stderr 与运行时诊断
bm2d.events.jsonl                   # 守护进程与监督事件
<name>/project.json                 # 一个项目的登记信息
<name>/<name>-<id>.json             # 持久化的实例状态
<name>/logs/<name>-<id>.out.log     # 应用 stdout
<name>/logs/<name>-<id>.error.log   # 应用 stderr
<name>/logs/<name>-<id>.crash.log   # 异常退出诊断

目录以 0700 创建,因为里面放着授权控制守护进程的令牌。

两类日志,严格分开 ​

<name>/logs/ 下的三份日志属于应用,由应用自己写入。顶层的三份属于 bm2,记录管理侧做了什么。分开的好处很直接:对应用日志 tail -f 读到的全是应用输出,而管理侧的历史小到可以长期保留。

出问题时这个划分尤其重要:应用崩了,它写自己的 .error.log 与 .crash.log;而「要不要重启、为什么」记在 bm2d.events.jsonl 里。

轮转 ​

单个文件超过 [logs] max_size_mb 即轮转一次,[logs] keep 决定保留几代归档。默认的 keep = 0 保留所有代数,所以磁盘占用的唯一上界就是你设的那个。

守护进程自身的日志不属于任何项目,因此不受任何项目的 [logs] 支配,统一用内置策略。

两种轮转方式都用上了,用哪一种取决于文件被谁握着。应用的 stdout 与 stderr 由应用自己持有 fd,所以先把内容拷出来再原地截断——改名会让应用继续往旧 inode 写,而新文件永远是空的。bm2 自己写的日志走改名,更省也更不丢东西。

实例状态文件的用途 ​

<name>/<name>-<id>.json 记录守护进程把一个实例重新接上所需的东西:pid、启动时间、重启次数、最后一次退出的原因。

它的用途只有一个——守护进程重启之后,新守护进程收养仍在运行的实例,而不是把它们再启动一份。它不记录日志、不记录环境变量值、不记录配置内容。

事件日志 ​

两个 *.events.jsonl 每行一个 JSON 对象。它们只记录管理元数据:时间戳、事件名、适用时的应用/实例/PID,以及运维原因。

它们不包含环境变量值、协议载荷、应用输出,也不包含通知凭据。

bash
tail -f ~/.bm2/bm2d.events.jsonl      # 盯着守护进程
jq -c . ~/.bm2/bm2d.events.jsonl      # 按字段过滤