编程

Fnos Openclaw Autostart

试用

FnOS OpenClaw 开机自启补丁 + 管理页面开关。修改监控端 server/index.js 和 ui/index.html,实现可开关的开机启动。

它能做什么

FnOS OpenClaw 开机自启补丁 + 管理页面开关。修改监控端 server/index.js 和 ui/index.html,实现可开关的开机启动。

技能文档

FnOS OpenClaw 开机自启补丁

问题

FnOS 应用中心(trim_app_center)会在开机时自动启动 OpenClaw 的监控端,但不会自动启动 openclaw-gateway。用户必须每次在应用面板手动点击「启动」。

本补丁注入自动启动逻辑到监控端,并添加管理页面开关(持久化),让用户能够在界面上启用/禁用开机自启。

前置条件

MONITOR_JS="/vol1/@appcenter/trim.openclaw/server/index.js"
UI_HTML="/vol1/@appcenter/trim.openclaw/ui/index.html"
AUTOSTART_CONF="/vol1/@appdata/trim.openclaw/.autostart"

步骤

1. 验证环境 & 查找注入点

先确认文件存在和当前行号(不同版本行号不同,绝不要硬编码):

# 确认文件存在
ls -la "$MONITOR_JS" "$UI_HTML"

# 创建 .autostart(默认启用),这是持久化状态文件
# 如果已存在则保留原值
if [ ! -f "$AUTOSTART_CONF" ]; then
  echo "1" > "$AUTOSTART_CONF"
  echo "Created $AUTOSTART_CONF with default enabled"
else
  echo "$AUTOSTART_CONF already exists: $(cat $AUTOSTART_CONF)"
fi

# 找 autostart 函数定义插入点:startRuntimeReconciler 行
echo "=== 函数定义插入点 ==="
grep -n "startRuntimeReconciler" "$MONITOR_JS"

# 找函数调用插入点:registerBackgroundTaskSafetyHandlers 行
echo "=== 函数调用插入点 ==="
grep -n "registerBackgroundTaskSafetyHandlers" "$MONITOR_JS"

# 找 API 路由插入点:telemetry_default 行
echo "=== API 路由插入点 ==="
grep -n "telemetry_default" "$MONITOR_JS"

# 检查是否已有补丁(避免重复注入)
echo "=== 检查是否已补丁 ==="
if grep -q "AUTOSTART_CONF" "$MONITOR_JS"; then
  echo "已有补丁,跳过注入"
else
  echo "尚无补丁,继续"
fi

# 检查 index.html 尾行
echo "=== 前端注入点 ==="
tail -5 "$UI_HTML"

# 确认 Bun bundle 上下文(是否 ES module,影响 require 用法)
head -1 "$MONITOR_JS"

2. 备份

cp "$MONITOR_JS" "${MONITOR_JS}.bak"
cp "$UI_HTML" "${UI_HTML}.bak"

3. server/index.js — 注入 autostart 逻辑

3.1 插入 autoStartDefaultInstance 函数定义

startRuntimeReconciler()之前插入:

sed -i '/^async function startRuntimeReconciler\|^startRuntimeReconciler()/i\
const AUTOSTART_CONF = "\/vol1\/@appdata\/trim.openclaw\/.autostart";\
async function autoStartDefaultInstance() { try {\
    const autoStartFlag = import.meta.require("fs").existsSync(AUTOSTART_CONF)\
      ? import.meta.require("fs").readFileSync(AUTOSTART_CONF, "utf8").trim()\
      : "1";\
    if (autoStartFlag === "0" || autoStartFlag === "false" || autoStartFlag === "disable") {\
      console.log("[monitor] Auto-start is disabled by " + AUTOSTART_CONF); return;\
    }\
    const instance = ensureDefaultInstance();\
    const runtime = await probeInstanceRuntime(instance);\
    if (runtime.running) { console.log("[monitor] OpenClaw gateway is already running, skipping auto-start"); return; }\
    if (!runtime.installed) { console.log("[monitor] OpenClaw is not installed, skipping auto-start"); return; }\
    console.log("[monitor] Auto-starting OpenClaw gateway on boot...");\
    let port = runtime.port;\
    if (!port) { port = randomPort(); await writeInstancePort(instance, port); }\
    const noopEnqueue = () => {};\
    await startOpenclaw(instance, port, noopEnqueue, null);\
    console.log("[monitor] OpenClaw gateway auto-started successfully");\
  } catch (err) { console.error("[monitor] Auto-start failed:", err); }\
}' "$MONITOR_JS"

⚠️ 关键注意事项

  • Bun bundle 是 ES module 上下文,必须用 import.meta.require("fs"),不能用 require("fs")(会抛 require is not defined
  • 如果函数定义行格式不同(如无 async 前缀),手动检查后调整 sed 匹配模式

3.2 插入函数调用

registerBackgroundTaskSafetyHandlers()之后插入:

sed -i '/^ *registerBackgroundTaskSafetyHandlers()/a\
autoStartDefaultInstance().catch((err) => {\
  console.error("[monitor] auto-start default instance failed:", err);\
});' "$MONITOR_JS"

3.3 插入 API 路由(GET + POST)

telemetry_default 路由之后插入:

sed -i '/telemetry_default/a\
app10.get(`${apiBase}\/autostart`, async (c3) => {\
  try {\
    const exists = import.meta.require("fs").existsSync(AUTOSTART_CONF);\
    const val = exists ? import.meta.require("fs").readFileSync(AUTOSTART_CONF, "utf8").trim() : "1";\
    return c3.json({ enabled: val !== "0" && val !== "false" && val !== "disable" });\
  } catch (err) { return c3.json({ enabled: true }, 500); }\
});\
app10.post(`${apiBase}\/autostart`, async (c3) => {\
  try {\
    const body = await c3.req.json();\
    if (body && typeof body.enabled === "boolean") {\
      import.meta.require("fs").writeFileSync(AUTOSTART_CONF, body.enabled ? "1" : "0", "utf8");\
      return c3.json({ ok: true, enabled: body.enabled });\
    }\
    return c3.json({ ok: false, message: "invalid body" }, 400);\
  } catch (err) { return c3.json({ ok: false, message: err.message }, 500); }\
});' "$MONITOR_JS"

4. ui/index.html — 注入 toggle 脚本

在 `` 之前插入脚本(建议使用 Python 或手动编辑,大型 sed 易错):

SPA 路由切换时:离开首页 → 卡片 DOM 移除 → toggle 自动消失;切回首页 → MutationObserver 检测到变化 → 重新 inject()

5. 验证

# 确认后端所有插入点
grep -n "AUTOSTART_CONF\|autoStartDefaultInstance\|autostart\|startRuntimeReconciler\|registerBackgroundTaskSafetyHandlers" "$MONITOR_JS"

# 确认前端开关脚本注入
grep -c "oc-autostart-wrap" "$UI_HTML"

# 确认无旧版 require("fs") 残留
grep 'require("fs")' "$MONITOR_JS" || echo "OK: no require('fs') found"

# 确认 .autostart 存在
ls -la "$AUTOSTART_CONF"

6. 重启监控端生效

FnOS 应用面板停止 → 启动 OpenClaw,或 kill 监控进程:

ps aux | grep "bun.*server/index.js" | grep -v grep
kill 

验证

  1. 进入管理页面 → 卡片头部"打开OpenClaw"按钮左侧应有「开机自启」开关
  2. 默认开启(蓝色),点击可关闭(灰色),加载时半透明
  3. 切到其他页面再回来 → 开关重新出现
  4. 关机重启 NAS → 开关开启时 gateway 自动启动,关闭时不启动
  5. 开关状态持久化(存储在 $AUTOSTART_CONF

手动开关(命令行)

# 关闭
echo "0" > $AUTOSTART_CONF
# 开启
echo "1" > $AUTOSTART_CONF
# 查看状态
cat $AUTOSTART_CONF

应用更新后重新打补丁

FnOS 应用中心更新时会替换 server/index.jsui/index.html,补丁会被覆盖。

重新打补丁:

  1. 检查备份:ls -la "$BAK_FILE" "${UI_HTML}.bak"
  2. 重复步骤 1-6
  3. 如果备份丢失,使用本 skill 重新完成全部步骤

回滚

cp "${MONITOR_JS}.bak" "$MONITOR_JS"
cp "${UI_HTML}.bak" "$UI_HTML"
# 重启监控端

关键注意事项

技术细节

  • 必须用 import.meta.require("fs"):Bun bundle 是 ES module 上下文,require 不可用
  • 不要乐观更新:点击开关后等 API 返回成功再翻转,失败则恢复
  • 加载态样式opacity: 0.5 + pointer-events: none
  • .autostart 默认 "1"(启用),保证向后兼容

维护注意

  • 不要硬编码行号:每次更新后 grep -n 确认实际行号
  • 不要硬编码路径:开头变量根据实际环境调整
  • 不同 FnOS 版本路径可能变化
  • Bun bundle 的函数定义格式可能随版本变化,sed 匹配模式需要微调

相关技能

Keep OpenClaw gateway alive: heartbeat monitoring, auto-restart, crash alerts, memory warning, uptime report.

3 次安装

Use when updating OpenClaw or debugging an OpenClaw instance after an update. This skill acts as a structured update runbook with emphasis on gateway startup...

21 次安装2 星标

通过多轮引导式问答,生成完整的 OpenClaw 个人 AI 助手配置文件。

24 次安装

零停机升级 OpenClaw:查 release notes → 主公确认 → 旁路备份 → npm install → 重启 + 回滚兜底

作者 LuffertLu

OpenClaw版本升级标准流程。每次说"升级openclaw"、"openclaw升级"、"更新openclaw"时必须执行,先做环境探测+分类,再按Windows/schtasks或Linux/systemd分支走对应升级方案

20 次安装