02-启动流程
第二章 · 启动流程
OpenClaw 的启动流程分为三个关键阶段:Node.js 启动器 (openclaw.mjs) → TypeScript 入口 (src/entry.ts) → CLI 运行时 (src/cli/run-main.ts)。
2.1 整体流程
用户敲下命令
│
▼
┌─────────────────────────────────┐
│ openclaw.mjs (Node.js 启动器) │
│ ① 检查 Node 版本 ≥ 22.14 │
│ ② 智能编译缓存处理 │
│ ③ 加载 dist/entry.js │
└────────────┬────────────────────┘
│
▼
┌─────────────────────────────────┐
│ src/entry.ts (TypeScript 入口) │
│ ① 主模块守卫 │
│ ② CLI 重生 (respawn) 检查 │
│ ③ 环境初始化 │
│ ④ 命令行参数解析 │
│ ⑤ Profile/Container 处理 │
└────────────┬────────────────────┘
│
▼
┌─────────────────────────────────┐
│ run-main.ts (CLI 运行时) │
│ ① Commander 命令注册 │
│ ② 子命令分发 │
│ ③ Gateway / Agent 启动 │
└─────────────────────────────────┘
2.2 第一阶段:openclaw.mjs 启动器
openclaw.mjs 是 npm 包中定义的 bin 入口,它是用户敲下 openclaw 命令后第一个执行的脚本。
2.2.1 Node 版本检查
// openclaw.mjs:11-42
const MIN_NODE_MAJOR = 22;
const MIN_NODE_MINOR = 12;
const parseNodeVersion = (rawVersion) => {
const [majorRaw = "0", minorRaw = "0"] = rawVersion.split(".");
return { major: Number(majorRaw), minor: Number(minorRaw) };
};
const isSupportedNodeVersion = (version) =>
version.major > MIN_NODE_MAJOR ||
(version.major === MIN_NODE_MAJOR && version.minor >= MIN_NODE_MINOR);
如果 Node 版本过低,会输出友好的错误信息并提示使用 nvm 升级。
2.2.2 智能编译缓存策略
这是 OpenClaw 启动器最精妙的设计之一:两级编译缓存重生策略。
// openclaw.mjs:87-153
// 阶段一:源码检出时禁用缓存
const respawnWithoutCompileCacheIfNeeded = () => {
if (!isSourceCheckoutLauncher()) return false; // 非源码环境不需要
if (OPENCLAW_SOURCE_COMPILE_CACHE_RESPAWNED) return false; // 已重生过
// ... 设置 NODE_DISABLE_COMPILE_CACHE=1,重新 spawn 进程
};
// 阶段二:打包安装时使用版本化缓存
const respawnWithPackagedCompileCacheIfNeeded = () => {
if (isSourceCheckoutLauncher()) return false; // 源码环境跳过
if (OPENCLAW_PACKAGED_COMPILE_CACHE_RESPAWNED) return false;
// ... 计算缓存目录路径,设置 NODE_COMPILE_CACHE,重新 spawn
};
缓存目录路径计算逻辑:
缓存目录 = {tmpdir}/node-compile-cache/openclaw/{version}/{installMarker}
其中 installMarker = {package.json 修改时间}-{package.json 大小}
这样设计的优势:
- 源码开发环境:禁用缓存,确保每次运行最新代码
- 生产安装环境:启用版本化缓存,大幅提升启动速度(避免重复编译 TypeScript)
- 升级安全:版本号和安装标记共同构成缓存键,升级后自动使用新缓存
2.2.3 编译缓存启用时机
// openclaw.mjs:155-162
if (module.enableCompileCache &&
!isNodeCompileCacheDisabled() &&
!isSourceCheckoutLauncher()) {
try {
module.enableCompileCache(resolvePackagedCompileCacheDirectory());
} catch {
// Ignore errors
}
}
注意,这里的 module.enableCompileCache 是 Node.js 22+ 的实验性 API:
- 在两次重生尝试之后才启用缓存,避免无效缓存污染
- 仅在打包安装环境启用(非源码检出)
2.2.4 快速帮助路径
启动器为 --help 和 -h 提供了快速路径,无需加载完整运行时:
// openclaw.mjs:242-313
const isBareRootHelpInvocation = (argv) =>
argv.length === 3 && (argv[2] === "--help" || argv[2] === "-h");
// 优先从预计算的 JSON 文件读取帮助文本
const precomputed = loadPrecomputedHelpText("rootHelpText");
if (precomputed) {
process.stdout.write(precomputed);
return true;
}
// 回退到加载专用模块
const mod = await import("./dist/cli/program/root-help.js");
2.2.5 入口文件加载
如果快速路径不匹配,启动器尝试加载运行时代码:
// openclaw.mjs:304-313
if (await tryImport("./dist/entry.js")) {
// OK - 标准构建产物
} else if (await tryImport("./dist/entry.mjs")) {
// OK - 备用构建产物
} else {
throw new Error(await buildMissingEntryErrorMessage());
// 提示用户需要先运行 pnpm install && pnpm build
}
2.3 第二阶段:src/entry.ts TypeScript 入口
entry.ts 是 TypeScript 侧的真正入口,负责运行时初始化和 CLI 分发。
2.3.1 主模块守卫
// src/entry.ts:77-84
if (!isMainModule({
currentFile: fileURLToPath(import.meta.url),
wrapperEntryPairs: [
{ wrapperBasename: "openclaw.mjs", entryBasename: "entry.js" },
{ wrapperBasename: "openclaw.js", entryBasename: "entry.js" },
],
})) {
// 作为依赖被导入 —— 跳过入口副作用
} else {
// 作为主模块 —— 执行启动逻辑
}
这个守卫设计是因为:
dist/index.js是 npm 包的主导出,也会 importentry.js- 没有这个守卫,
entry.ts的顶层代码会被执行两次,导致端口冲突和锁文件竞争
2.3.2 环境初始化序列
// src/entry.ts:85-98
process.title = "openclaw"; // 设置进程名
ensureOpenClawExecMarkerOnProcess(); // 标记当前为 OpenClaw 进程
installProcessWarningFilter(); // 安装警告过滤器
normalizeEnv(); // 标准化环境变量
enableOpenClawCompileCache({ installRoot }); // 启用编译缓存
gatewayEntryStartupTrace.mark("bootstrap"); // 启动追踪标记
2.3.3 启动追踪(Gateway Startup Trace)
entry.ts 内置了一个可选的 Gateway 启动性能追踪器:
// src/entry.ts:37-68
function createGatewayEntryStartupTrace(argv: string[]) {
const enabled = isTruthyEnvValue(OPENCLAW_GATEWAY_STARTUP_TRACE)
&& argv.slice(2).includes("gateway");
// ...
return {
mark(name: string) { /* 记录时间戳 */ },
async measure<T>(name: string, run: () => Promise<T>): Promise<T> { /* 测量异步操作 */ }
};
}
设置 OPENCLAW_GATEWAY_STARTUP_TRACE=1 后,启动时的每个关键阶段都会被标记和输出。
2.3.4 CLI 重生逻辑
// src/entry.ts:109-140
function ensureCliRespawnReady(): boolean {
const plan = buildCliRespawnPlan(); // 检查是否需要重生
if (!plan) return false;
// 用新的 Node 进程 spawn 自身
const child = spawn(plan.command, plan.argv, {
stdio: "inherit",
env: plan.env,
});
// 父进程等待子进程结束
child.once("exit", (code, signal) => process.exit(code ?? 1));
return true;
}
重生逻辑主要处理跨平台兼容性问题,比如 Windows 上的 node vs node.exe 差异。
2.3.5 Profile 和 Container 参数解析
// src/entry.ts:145-169
const parsedContainer = parseCliContainerArgs(process.argv); // --container <name>
const parsed = parseCliProfileArgs(parsedContainer.argv); // --profile <name> / --dev
// 冲突检测:--container 和 --profile 不能同时使用
if (containerTargetName && parsed.profile) {
console.error("[openclaw] --container cannot be combined with --profile/--dev");
process.exit(2);
}
if (parsed.profile) {
applyCliProfileEnv({ profile: parsed.profile }); // 应用 Profile 环境变量
process.argv = parsed.argv;
}
2.3.6 最终分发
// src/entry.ts:220-237
async function runMainOrRootHelp(argv: string[]): Promise<void> {
if (await tryHandleRootHelpFastPath(argv)) return; // --help 快速路径
const { runCli } = await import("./cli/run-main.js"); // 动态导入 CLI 运行时
await runCli(argv); // 委托给 Commander
}
2.4 总结:启动路径决策树
openclaw <args>
│
├── Node < 22.14? → 报错退出
│
├── 源码环境? → 禁用缓存重生 → 重新 spawn
│
├── 打包环境? → 版本化缓存重生 → 重新 spawn
│
├── --help / -h? → 快速帮助路径 → 直接输出
│
├── 加载 dist/entry.js 失败? → 提示 build
│
└── 正常加载 →
├── 主模块检查
├── 环境初始化
├── CLI 重生检查
├── Profile/Container 解析
└── runCli() → Commander 命令分发
关键设计亮点
- 两级编译缓存:源码头和打包头使用不同策略,兼顾开发体验和生产性能
- 快速帮助路径:
--help不需要完整启动,毫秒级响应 - 主模块守卫:防止作为依赖导入时副作用重复执行
- 懒加载:
src/cli/run-main.ts通过动态import()加载,减少启动时的初始化开销
下章预告:命令行系统 —— Commander.js 框架、子命令注册、Profile 机制。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)