English | 中文
Summary
On macOS with a non-English system language (LANG=zh_CN.UTF-8 in this report), offckb node stop exits 1 and refuses to signal the daemon it started itself: verifyDaemonIdentity() reads the process start time with ps -o lstart= and parses it with an English-only pattern, so a localized line is treated as "not our daemon". The daemon keeps running, so clean is blocked as well. @offckb/cli@0.4.13 stops the same daemon normally on this machine, so this is a regression introduced with the Fiber work (#483), the change that added this start-time check. Workaround: run the stop command with LC_ALL=C.
What I ran into
On a Mac whose system language is Chinese, OffCKB 0.5.0-canary-ee0ad6b starts the devnet daemon normally but cannot stop it. node stop exits with code 1 and refuses to signal the daemon it started itself:
{"ok":false,"code":"COMMAND_FAILED","message":"Process 93563 does not appear to be the offckb daemon. Refusing to send signals to avoid killing an unrelated process. If you are sure this is the daemon, stop it manually and remove .../devnet/data/logs/daemon.pid."}
Paths in the quoted output are abbreviated with ....
The same command with LC_ALL=C succeeds immediately and reports {"ok":true,"command":"node.stop","stopped":true,"pid":93563}. The only difference between the two runs is the locale, so the daemon identity check is reading localized output and failing closed.
Reproduction
Run the published canary (0.5.0-canary-ee0ad6b) from npm in a fresh, isolated user directory. The second and third stop commands target the same daemon process; only the locale of the stop command changes.
case_root=$(mktemp -d)
mkdir -p "$case_root/home"
export HOME="$case_root/home"
export XDG_DATA_HOME="$HOME/.local/share"
export XDG_CONFIG_HOME="$HOME/.config"
export XDG_CACHE_HOME="$HOME/.cache"
export XDG_STATE_HOME="$HOME/.local/state"
export LANG=zh_CN.UTF-8
unset LC_ALL LC_TIME
offckb --json node --daemon --binary-path /absolute/path/to/ckb-0.208.0/ckb
offckb --json node stop
LC_ALL=C offckb --json node stop
Observed: the daemon starts (exit 0), the first node stop exits 1 with empty stdout, and the second node stop under LC_ALL=C exits 0 for that same PID.
$ node --version
v22.23.2
$ offckb --version
0.5.0-canary-ee0ad6b
$ locale
LANG="zh_CN.UTF-8"
LC_COLLATE="zh_CN.UTF-8"
LC_CTYPE="zh_CN.UTF-8"
$ ps -p <pid> -o lstart= # what OffCKB reads with the inherited locale
五 9月/25 20:28:43 2026
$ LC_ALL=C ps -p <pid> -o lstart=
Fri Sep 25 20:28:43 2026
Cause
verifyDaemonIdentity() (src/util/daemon.ts L425-L455) compares the daemon's command line and its process start time. On macOS the start time comes from ps:
The product then refuses to signal the process.
Why this could affect normal use
- Reachable on a normal upgrade. The daemon starts, so the failure appears only later, when the user tries to stop or clean up, and the environment stays running until the command is run under a different locale. The error message's suggestion — stop the process manually, then remove the PID file — asks the user to identify and kill OffCKB's own daemon by hand.
- It blocks the standard stop path.
node stop is the stop command that fails here; the error message instead asks the user to stop the process manually. fiber stop performs the same identity check with Fiber-specific wording (src/fiber/daemon.ts L309-L312), and fiber status uses it to decide the offckbManaged field — both are code-path expectations that I did not reproduce.
- Cleanup is blocked as a consequence, not by the same check.
clean refuses while the CKB daemon is running (src/cmd/clean.ts L18-L20); inside a running Fiber environment, fiber clean likewise requires the Fiber nodes to be stopped first (src/fiber/clean.ts). That refusal is correct behaviour — the problem is the stop they depend on. Only the plain-CKB path was exercised here.
- Platform scope. macOS is affected through the
ps path. On Linux the code reads /proc first, which avoids ps entirely; if that read fails it falls back to ps, so Linux is not categorically safe. I could not test Linux, so this is an expectation rather than a reproduced result.
- Other locales with the same mechanism. Any locale that makes
ps print a non-English lstart should hit the same path; I only reproduced it with the Chinese locale.
This is a regression from 0.4.13
I ran the same start/stop sequence with @offckb/cli@0.4.13 on this machine, under the same Chinese locale, and then compared the two builds:
@offckb/cli@0.4.13: node --daemon exits 0, and node stop exits 0 with {"ok":true,"command":"node.stop","stopped":true,"pid":98610}. Its verifyDaemonIdentity() only inspects the process command line through ps -o args=; it reads no start time at all, and lstart does not appear anywhere in that build.
0.5.0-canary-ee0ad6b: the start-time comparison and the parsePsLstart regex are new, and this is what fails on a localized ps.
The difference between the two versions is the new check, so this is a regression introduced with the Fiber work rather than long-standing behaviour.
Each version ran in its own fresh temporary HOME/XDG pair, so the two PIDs above come from separate environments. Both runs used the same machine, the same CKB 0.208.0 binary and the same inherited locale:
# @offckb/cli@0.4.13
$ node .../offckb-0.4.13/build/index.js --version
0.4.13
$ ps -p $$ -o lstart= # output format with the inherited locale
五 9月/25 20:40:55 2026
$ grep -c lstart build/index.js
0
$ node .../build/index.js --json node --daemon --binary-path <ckb> -> exit 0
$ node .../build/index.js --json node stop -> exit 0
{"ok":true,"command":"node.stop","stopped":true,"pid":98610}
# 0.5.0-canary-ee0ad6b, same machine and locale
$ node .../build/index.js --json node --daemon --binary-path <ckb> -> exit 0
$ node .../build/index.js --json node stop -> exit 1, stdout empty
{"ok":false,"code":"COMMAND_FAILED","message":"Process 93563 does not appear to be the offckb daemon. ..."}
$ LC_ALL=C node .../build/index.js --json node stop -> exit 0
{"ok":true,"command":"node.stop","stopped":true,"pid":93563}
What I would expect
- Stopping or cleaning a devnet that OffCKB itself started should work regardless of the operating system language.
- Keep the start-time identity check: it is what prevents signaling an unrelated process that reused the daemon's PID, and skipping it when the time cannot be read would weaken that protection. The fix belongs in how the time is read: run the
ps child with a fixed locale, for example env: { ...process.env, LC_ALL: 'C' }, so lstart can be parsed consistently. If the probe still fails, report that the process identity could not be verified and signal nothing — "cannot verify" may shape the error message, but it should not become a condition that allows stopping.
- While preparing this report I checked whether
ps -o etimes= (elapsed seconds) could replace lstart with a locale-independent value. On macOS that keyword does not exist (ps: etimes: keyword not found; the manual lists etime), so I removed that suggestion.
Environment
@offckb/cli@0.5.0-canary-ee0ad6b, installed from npm and checked with offckb --version.
- macOS arm64; Node.js
22.23.2; the stop command inherited LANG=zh_CN.UTF-8 (with LC_ALL and LC_TIME unset), which is what the reproduction uses.
- CKB
0.208.0; separate temporary HOME/XDG directories for these checks, no developer data involved.
I can share the raw command output, ps samples or daemon logs for either version if that helps.
Source references
Supporting source code in the tested canary
The comparison against 0.4.13 was made on the published npm tarballs (cli-0.4.13.tgz and the canary tarball), not on a local build.
中文版
系统语言不是英文时,macOS 上的 node stop 会拒绝停止它自己启动的守护进程
摘要
在系统语言不是英文的 macOS 上(本报告为 LANG=zh_CN.UTF-8),offckb node stop 退出码为 1,并拒绝给它自己启动的守护进程发信号:verifyDaemonIdentity() 用 ps -o lstart= 读取进程启动时间,再用只认英文的正则解析,于是本地化的输出被当成"这不是我们的 daemon"。daemon 因此一直运行,clean 也因它而按设计拒绝执行。同一台机器上,@offckb/cli@0.4.13 可以正常停止同一个 daemon,所以这是随 Fiber 功能(#483,即引入该启动时间校验的改动)引入的回归。临时绕过办法:停止命令前加 LC_ALL=C。
我遇到的情况
在系统语言为中文的 Mac 上,OffCKB 0.5.0-canary-ee0ad6b 能正常启动 devnet daemon,却无法停止它。node stop 退出码为 1,并且拒绝给它自己启动的 daemon 发信号:
{"ok":false,"code":"COMMAND_FAILED","message":"Process 93563 does not appear to be the offckb daemon. Refusing to send signals to avoid killing an unrelated process. If you are sure this is the daemon, stop it manually and remove .../devnet/data/logs/daemon.pid."}
引用的输出中,路径已用 ... 缩写。
同一条命令加上 LC_ALL=C 立刻成功,返回 {"ok":true,"command":"node.stop","stopped":true,"pid":93563}。两次运行唯一的差别就是 locale,说明守护进程身份校验读到了本地化输出并因此判定失败。
复现步骤
使用 npm 上发布的 canary(0.5.0-canary-ee0ad6b),在全新的隔离用户目录中执行。第二条和第三条停止命令针对同一个 daemon 进程,只有停止命令的 locale 不同。
case_root=$(mktemp -d)
mkdir -p "$case_root/home"
export HOME="$case_root/home"
export XDG_DATA_HOME="$HOME/.local/share"
export XDG_CONFIG_HOME="$HOME/.config"
export XDG_CACHE_HOME="$HOME/.cache"
export XDG_STATE_HOME="$HOME/.local/state"
export LANG=zh_CN.UTF-8
unset LC_ALL LC_TIME
offckb --json node --daemon --binary-path /absolute/path/to/ckb-0.208.0/ckb
offckb --json node stop
LC_ALL=C offckb --json node stop
实测结果:daemon 启动成功(退出码 0),第一条 node stop 退出码 1 且 stdout 为空,第二条加 LC_ALL=C 的 node stop 对同一个 PID 退出码 0。
$ node --version
v22.23.2
$ offckb --version
0.5.0-canary-ee0ad6b
$ locale
LANG="zh_CN.UTF-8"
LC_COLLATE="zh_CN.UTF-8"
LC_CTYPE="zh_CN.UTF-8"
$ ps -p <pid> -o lstart= # OffCKB 继承 locale 后读到的内容
五 9月/25 20:28:43 2026
$ LC_ALL=C ps -p <pid> -o lstart=
Fri Sep 25 20:28:43 2026
原因
verifyDaemonIdentity()(src/util/daemon.ts L425-L455)既比对守护进程命令行,也比对它读取到的进程启动时间。在 macOS 上启动时间来自 ps:
产品因此拒绝发送信号。
为什么这可能影响日常使用
- 它挡住了标准的停止入口。 本次失败的命令就是
node stop;错误提示转而要求用户手动停止进程。fiber stop 使用同一身份校验、只是提示文本不同(src/fiber/daemon.ts L309-L312),fiber status 的 offckbManaged 字段也由它决定——这两条属于代码推断,我没有实测。
- 清理是被间接阻塞的,不是同一个校验。
clean 在 CKB daemon 仍在运行时按设计拒绝(src/cmd/clean.ts L18-L20);在运行中的 Fiber 环境里,fiber clean 同样要求先停止 Fiber 节点(src/fiber/clean.ts)。拒绝本身是正确的,问题在于它们依赖的停止命令不可用。本次只验证了普通 CKB devnet 这条路径。
- 平台范围。 macOS 走
ps 这条路。Linux 上代码优先读 /proc,直接绕开 ps;只有当 /proc 读取失败时才会回退到 ps,所以 Linux 并非绝对安全。我没有 Linux 机器实测,这是推断而非复现结果。
- 其他会使
ps 输出本地化 lstart 的 locale 应当命中同一路径;我只用中文 locale 复现过。
这是相对 0.4.13 的回归
我在同一台机器、同一中文 locale 下用 @offckb/cli@0.4.13 跑了相同的启动/停止流程,再对比两个构建:
@offckb/cli@0.4.13:node --daemon 退出码 0,node stop 退出码 0,输出 {"ok":true,"command":"node.stop","stopped":true,"pid":98610}。它的 verifyDaemonIdentity() 只通过 ps -o args= 检查命令行,完全不读启动时间,该构建里也不出现 lstart。
0.5.0-canary-ee0ad6b:新增了启动时间比对与 parsePsLstart 正则,本地化的 ps 输出正是失败点。
两个版本的差异就是这个新校验,因此这是随 Fiber 功能一起引入的回归,而不是长期存在的行为。
两个版本各自使用全新的临时 HOME/XDG,因此上面的两个 PID 来自彼此独立的环境。两次运行使用同一台机器、同一个 CKB 0.208.0 二进制和同一套继承的 locale:
# @offckb/cli@0.4.13
$ node .../offckb-0.4.13/build/index.js --version
0.4.13
$ ps -p $$ -o lstart= # 继承 locale 后的输出格式
五 9月/25 20:40:55 2026
$ grep -c lstart build/index.js
0
$ node .../build/index.js --json node --daemon --binary-path <ckb> -> 退出码 0
$ node .../build/index.js --json node stop -> 退出码 0
{"ok":true,"command":"node.stop","stopped":true,"pid":98610}
# 0.5.0-canary-ee0ad6b,同一台机器、同一 locale
$ node .../build/index.js --json node --daemon --binary-path <ckb> -> 退出码 0
$ node .../build/index.js --json node stop -> 退出码 1,stdout 为空
{"ok":false,"code":"COMMAND_FAILED","message":"Process 93563 does not appear to be the offckb daemon. ..."}
$ LC_ALL=C node .../build/index.js --json node stop -> 退出码 0
{"ok":true,"command":"node.stop","stopped":true,"pid":93563}
我希望的行为
- OffCKB 自己启动的 devnet,无论操作系统语言是什么,都应该能正常停止和清理。
- 保留启动时间校验:它正是防止 PID 被复用后误杀无关进程的保护;在读不到时间时跳过校验会削弱这层保护。要修的是"怎么读时间":给
ps 子进程固定 locale,例如 env: { ...process.env, LC_ALL: 'C' },让 lstart 能被稳定解析。若探测仍然失败,应报告"无法确认进程身份"并且不发任何信号——"无法判定"可以影响错误提示,但不应变成允许停止的降级条件。
- 准备这份报告时我核对过用
ps -o etimes=(已运行秒数)替代 lstart 的可行性:macOS 没有这个关键字(ps: etimes: keyword not found,手册只列 etime),因此删去了该建议。
环境
@offckb/cli@0.5.0-canary-ee0ad6b,从 npm 安装,用 offckb --version 核对。
- macOS arm64;Node.js
22.23.2;停止命令继承的是 LANG=zh_CN.UTF-8(LC_ALL、LC_TIME 未设置),复现步骤即以此为准。
- CKB
0.208.0;上述检查都在独立的临时 HOME/XDG 目录中完成,未使用开发者真实数据。
如需复核,我可以补上两个版本的原始命令输出、ps 采样或 daemon 日志。
问题溯源
被测 canary 中的相关源码
与 0.4.13 的对比基于两个已发布的 npm 包(cli-0.4.13.tgz 与 canary tarball),不是本地构建。
English | 中文
Summary
On macOS with a non-English system language (
LANG=zh_CN.UTF-8in this report),offckb node stopexits1and refuses to signal the daemon it started itself:verifyDaemonIdentity()reads the process start time withps -o lstart=and parses it with an English-only pattern, so a localized line is treated as "not our daemon". The daemon keeps running, socleanis blocked as well.@offckb/cli@0.4.13stops the same daemon normally on this machine, so this is a regression introduced with the Fiber work (#483), the change that added this start-time check. Workaround: run the stop command withLC_ALL=C.What I ran into
On a Mac whose system language is Chinese, OffCKB
0.5.0-canary-ee0ad6bstarts the devnet daemon normally but cannot stop it.node stopexits with code1and refuses to signal the daemon it started itself:{"ok":false,"code":"COMMAND_FAILED","message":"Process 93563 does not appear to be the offckb daemon. Refusing to send signals to avoid killing an unrelated process. If you are sure this is the daemon, stop it manually and remove .../devnet/data/logs/daemon.pid."}Paths in the quoted output are abbreviated with
....The same command with
LC_ALL=Csucceeds immediately and reports{"ok":true,"command":"node.stop","stopped":true,"pid":93563}. The only difference between the two runs is the locale, so the daemon identity check is reading localized output and failing closed.Reproduction
Run the published canary (
0.5.0-canary-ee0ad6b) from npm in a fresh, isolated user directory. The second and third stop commands target the same daemon process; only the locale of the stop command changes.Observed: the daemon starts (
exit 0), the firstnode stopexits1with empty stdout, and the secondnode stopunderLC_ALL=Cexits0for that same PID.Cause
verifyDaemonIdentity()(src/util/daemon.tsL425-L455) compares the daemon's command line and its process start time. On macOS the start time comes fromps:readPosixProcessInfo()L317-L322 runsps -p <pid> -o lstart=, andexecFileText()L304-L315 passes noenv, sopsinherits the user's locale and prints localized month and weekday names.parsePsLstart()L283-L297 parses that output with an English-only pattern:/^\w{3} (\w{3}) +(\d{1,2}) (\d{2}):(\d{2}):(\d{2}) (\d{4})$/.LSTART_MONTHSonly contains English month abbreviations.startTimeMsbecomesnull, and the identity check treats "cannot read the start time" as "this is not our daemon":if (info.startTimeMs == null) return false;L449.The product then refuses to signal the process.
Why this could affect normal use
node stopis the stop command that fails here; the error message instead asks the user to stop the process manually.fiber stopperforms the same identity check with Fiber-specific wording (src/fiber/daemon.tsL309-L312), andfiber statususes it to decide theoffckbManagedfield — both are code-path expectations that I did not reproduce.cleanrefuses while the CKB daemon is running (src/cmd/clean.tsL18-L20); inside a running Fiber environment,fiber cleanlikewise requires the Fiber nodes to be stopped first (src/fiber/clean.ts). That refusal is correct behaviour — the problem is the stop they depend on. Only the plain-CKB path was exercised here.pspath. On Linux the code reads/procfirst, which avoidspsentirely; if that read fails it falls back tops, so Linux is not categorically safe. I could not test Linux, so this is an expectation rather than a reproduced result.psprint a non-Englishlstartshould hit the same path; I only reproduced it with the Chinese locale.This is a regression from 0.4.13
I ran the same start/stop sequence with
@offckb/cli@0.4.13on this machine, under the same Chinese locale, and then compared the two builds:@offckb/cli@0.4.13:node --daemonexits0, andnode stopexits0with{"ok":true,"command":"node.stop","stopped":true,"pid":98610}. ItsverifyDaemonIdentity()only inspects the process command line throughps -o args=; it reads no start time at all, andlstartdoes not appear anywhere in that build.0.5.0-canary-ee0ad6b: the start-time comparison and theparsePsLstartregex are new, and this is what fails on a localizedps.The difference between the two versions is the new check, so this is a regression introduced with the Fiber work rather than long-standing behaviour.
Each version ran in its own fresh temporary
HOME/XDG pair, so the two PIDs above come from separate environments. Both runs used the same machine, the same CKB0.208.0binary and the same inherited locale:What I would expect
pschild with a fixed locale, for exampleenv: { ...process.env, LC_ALL: 'C' }, solstartcan be parsed consistently. If the probe still fails, report that the process identity could not be verified and signal nothing — "cannot verify" may shape the error message, but it should not become a condition that allows stopping.ps -o etimes=(elapsed seconds) could replacelstartwith a locale-independent value. On macOS that keyword does not exist (ps: etimes: keyword not found; the manual listsetime), so I removed that suggestion.Environment
@offckb/cli@0.5.0-canary-ee0ad6b, installed from npm and checked withoffckb --version.22.23.2; the stop command inheritedLANG=zh_CN.UTF-8(withLC_ALLandLC_TIMEunset), which is what the reproduction uses.0.208.0; separate temporaryHOME/XDG directories for these checks, no developer data involved.I can share the raw command output,
pssamples or daemon logs for either version if that helps.Source references
Supporting source code in the tested canary
verifyDaemonIdentity()requiresstartTimeMsto be present and withinDAEMON_START_TIME_TOLERANCE_MS(30_000).readPosixProcessInfo()runsps -p <pid> -o lstart=andparsePsLstart()parses the result with an English-only pattern; the helper that runsps(L304-L315) sets no locale.node stop— the failing branch and its message.fiber stopand the Fiber daemon checks — the same check with Fiber-specific wording.The comparison against 0.4.13 was made on the published npm tarballs (
cli-0.4.13.tgzand the canary tarball), not on a local build.中文版
系统语言不是英文时,macOS 上的
node stop会拒绝停止它自己启动的守护进程摘要
在系统语言不是英文的 macOS 上(本报告为
LANG=zh_CN.UTF-8),offckb node stop退出码为1,并拒绝给它自己启动的守护进程发信号:verifyDaemonIdentity()用ps -o lstart=读取进程启动时间,再用只认英文的正则解析,于是本地化的输出被当成"这不是我们的 daemon"。daemon 因此一直运行,clean也因它而按设计拒绝执行。同一台机器上,@offckb/cli@0.4.13可以正常停止同一个 daemon,所以这是随 Fiber 功能(#483,即引入该启动时间校验的改动)引入的回归。临时绕过办法:停止命令前加LC_ALL=C。我遇到的情况
在系统语言为中文的 Mac 上,OffCKB
0.5.0-canary-ee0ad6b能正常启动 devnet daemon,却无法停止它。node stop退出码为1,并且拒绝给它自己启动的 daemon 发信号:{"ok":false,"code":"COMMAND_FAILED","message":"Process 93563 does not appear to be the offckb daemon. Refusing to send signals to avoid killing an unrelated process. If you are sure this is the daemon, stop it manually and remove .../devnet/data/logs/daemon.pid."}引用的输出中,路径已用
...缩写。同一条命令加上
LC_ALL=C立刻成功,返回{"ok":true,"command":"node.stop","stopped":true,"pid":93563}。两次运行唯一的差别就是 locale,说明守护进程身份校验读到了本地化输出并因此判定失败。复现步骤
使用 npm 上发布的 canary(
0.5.0-canary-ee0ad6b),在全新的隔离用户目录中执行。第二条和第三条停止命令针对同一个 daemon 进程,只有停止命令的 locale 不同。实测结果:daemon 启动成功(退出码
0),第一条node stop退出码1且 stdout 为空,第二条加LC_ALL=C的node stop对同一个 PID 退出码0。原因
verifyDaemonIdentity()(src/util/daemon.tsL425-L455)既比对守护进程命令行,也比对它读取到的进程启动时间。在 macOS 上启动时间来自ps:readPosixProcessInfo()L317-L322 执行ps -p <pid> -o lstart=,而execFileText()L304-L315 没有传env,于是ps继承用户 locale,输出本地化的月份和星期。parsePsLstart()L283-L297 用只认英文的正则解析:/^\w{3} (\w{3}) +(\d{1,2}) (\d{2}):(\d{2}):(\d{2}) (\d{4})$/,月份表也只包含英文缩写。startTimeMs变成null,而校验把"读不到启动时间"当成"这不是我们的 daemon":if (info.startTimeMs == null) return false;L449。产品因此拒绝发送信号。
为什么这可能影响日常使用
node stop;错误提示转而要求用户手动停止进程。fiber stop使用同一身份校验、只是提示文本不同(src/fiber/daemon.tsL309-L312),fiber status的offckbManaged字段也由它决定——这两条属于代码推断,我没有实测。clean在 CKB daemon 仍在运行时按设计拒绝(src/cmd/clean.tsL18-L20);在运行中的 Fiber 环境里,fiber clean同样要求先停止 Fiber 节点(src/fiber/clean.ts)。拒绝本身是正确的,问题在于它们依赖的停止命令不可用。本次只验证了普通 CKB devnet 这条路径。ps这条路。Linux 上代码优先读/proc,直接绕开ps;只有当/proc读取失败时才会回退到ps,所以 Linux 并非绝对安全。我没有 Linux 机器实测,这是推断而非复现结果。ps输出本地化lstart的 locale 应当命中同一路径;我只用中文 locale 复现过。这是相对 0.4.13 的回归
我在同一台机器、同一中文 locale 下用
@offckb/cli@0.4.13跑了相同的启动/停止流程,再对比两个构建:@offckb/cli@0.4.13:node --daemon退出码0,node stop退出码0,输出{"ok":true,"command":"node.stop","stopped":true,"pid":98610}。它的verifyDaemonIdentity()只通过ps -o args=检查命令行,完全不读启动时间,该构建里也不出现lstart。0.5.0-canary-ee0ad6b:新增了启动时间比对与parsePsLstart正则,本地化的ps输出正是失败点。两个版本的差异就是这个新校验,因此这是随 Fiber 功能一起引入的回归,而不是长期存在的行为。
两个版本各自使用全新的临时
HOME/XDG,因此上面的两个 PID 来自彼此独立的环境。两次运行使用同一台机器、同一个 CKB0.208.0二进制和同一套继承的 locale:我希望的行为
ps子进程固定 locale,例如env: { ...process.env, LC_ALL: 'C' },让lstart能被稳定解析。若探测仍然失败,应报告"无法确认进程身份"并且不发任何信号——"无法判定"可以影响错误提示,但不应变成允许停止的降级条件。ps -o etimes=(已运行秒数)替代lstart的可行性:macOS 没有这个关键字(ps: etimes: keyword not found,手册只列etime),因此删去了该建议。环境
@offckb/cli@0.5.0-canary-ee0ad6b,从 npm 安装,用offckb --version核对。22.23.2;停止命令继承的是LANG=zh_CN.UTF-8(LC_ALL、LC_TIME未设置),复现步骤即以此为准。0.208.0;上述检查都在独立的临时HOME/XDG 目录中完成,未使用开发者真实数据。如需复核,我可以补上两个版本的原始命令输出、
ps采样或 daemon 日志。问题溯源
被测 canary 中的相关源码
verifyDaemonIdentity()要求startTimeMs存在且与DAEMON_START_TIME_TOLERANCE_MS(30_000)之内。readPosixProcessInfo()执行ps -p <pid> -o lstart=,parsePsLstart()用只认英文的正则解析;执行ps的辅助函数(L304-L315)没有设置 locale。node stop—— 失败分支与提示文本。fiber stop与 Fiber 守护进程检查 —— 同一校验的 Fiber 版本提示。与 0.4.13 的对比基于两个已发布的 npm 包(
cli-0.4.13.tgz与 canary tarball),不是本地构建。