release: v1.0.15 — QQBot 死锁修复、离线安装包、musl 架构支持

This commit is contained in:
10000ge10000
2026-03-13 00:20:08 +08:00
parent a99283aee2
commit 3aa39512c0
18 changed files with 1870 additions and 170 deletions

View File

@@ -11,7 +11,7 @@
# ============================================================================
set -e
NODE_VERSION="${NODE_VERSION:-22.16.0}"
NODE_VERSION="${NODE_VERSION:-22.15.1}"
# 经过验证的 OpenClaw 稳定版本 (更新此值需同步测试)
OC_TESTED_VERSION="2026.3.8"
# 用户可通过 OC_VERSION 环境变量覆盖安装版本
@@ -145,7 +145,7 @@ download_node() {
return 0
fi
# ARM64 musl 使用 Alpine 打包,版本号可能不完全匹配
# 只要主版本号相同即认为兼容 (如 22.15.1 vs 22.16.0)
# 只要主版本号相同即认为兼容 (如 22.15.1 vs 22.15.0)
local cur_major=$(echo "$current_ver" | cut -d. -f1)
local want_major=$(echo "$node_ver" | cut -d. -f1)
if [ "$cur_major" = "$want_major" ]; then
@@ -418,7 +418,7 @@ do_setup() {
fi
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║ 一万AI分享 OpenClaw 环境安装 ║"
echo "║ 一万AI分享 OpenClaw 环境安装 ║"
echo "╚══════════════════════════════════════════════════════════════╝"
echo ""
echo " 架构: $(uname -m)"
@@ -439,15 +439,15 @@ do_setup() {
echo ""
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║ ✅ 安装完成! ║"
echo "║ ║"
echo "║ 下一步: ║"
echo "║ uci set openclaw.main.enabled=1 ║"
echo "║ uci commit openclaw ║"
echo "║ /etc/init.d/openclaw enable ║"
echo "║ /etc/init.d/openclaw start ║"
echo "║ ║"
echo "║ 或在 LuCI → 服务 → OpenClaw 中启用 ║"
echo "║ ✅ 安装完成! ║"
echo "║ ║"
echo "║ 下一步: ║"
echo "║ uci set openclaw.main.enabled=1 ║"
echo "║ uci commit openclaw ║"
echo "║ /etc/init.d/openclaw enable ║"
echo "║ /etc/init.d/openclaw start ║"
echo "║ ║"
echo "║ 或在 LuCI → 服务 → OpenClaw 中启用 ║"
echo "╚══════════════════════════════════════════════════════════════╝"
}
@@ -498,7 +498,7 @@ do_check() {
do_upgrade() {
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║ 一万AI分享 OpenClaw 升级 ║"
echo "║ 一万AI分享 OpenClaw 升级 ║"
echo "╚══════════════════════════════════════════════════════════════╝"
echo ""
@@ -549,7 +549,7 @@ do_upgrade() {
fi
echo ""
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║ ✅ 升级完成! ║"
echo "║ ✅ 升级完成! ║"
echo "╚══════════════════════════════════════════════════════════════╝"
else
log_error "升级验证失败OpenClaw 入口文件未找到"
@@ -623,11 +623,114 @@ do_factory_reset() {
log_info "出厂设置已恢复Gateway 重启中..."
}
# ── 离线安装 (从本地文件安装 Node.js + OpenClaw) ──
do_setup_offline() {
local offline_dir="${2:-/tmp/openclaw-offline}"
if [ ! -d "$offline_dir" ]; then
log_error "离线安装目录不存在: $offline_dir"
log_error "此命令通常由离线 .run 安装器自动调用"
exit 1
fi
# 检查是否已安装
if [ -x "$NODE_BIN" ] && [ -n "$(find_oc_entry)" ]; then
log_warn "OpenClaw 运行环境已安装"
log_warn "如需重新离线安装,请先卸载现有环境"
exit 0
fi
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║ 一万AI分享 OpenClaw 离线安装 ║"
echo "╚══════════════════════════════════════════════════════════════╝"
echo ""
echo " 架构: $(uname -m)"
echo " 安装路径: ${NODE_BASE}"
echo " 数据路径: ${OC_DATA}"
echo " 离线包: ${offline_dir}"
echo ""
# [1] 安装 Node.js
local node_tarball="$offline_dir/node.tar.xz"
if [ -f "$node_tarball" ]; then
echo "=== 安装 Node.js (离线) ==="
rm -rf "$NODE_BASE" 2>/dev/null
[ -d /overlay/upper ] && rm -rf "/overlay/upper${NODE_BASE}" 2>/dev/null
ensure_mkdir "$NODE_BASE"
if tar --strip-components=1 -xf "$node_tarball" -C "$NODE_BASE" 2>/dev/null; then
: # GNU tar
else
local tmp_extract="/tmp/node-extract-$$"
ensure_mkdir "$tmp_extract"
tar xf "$node_tarball" -C "$tmp_extract"
local top_dir=$(ls "$tmp_extract" 2>/dev/null | head -1)
if [ -n "$top_dir" ] && [ -d "$tmp_extract/$top_dir" ]; then
cp -a "$tmp_extract/$top_dir/." "$NODE_BASE/"
fi
rm -rf "$tmp_extract"
fi
if [ -x "$NODE_BIN" ]; then
log_info "Node.js $($NODE_BIN --version 2>/dev/null) 安装成功"
else
log_error "Node.js 安装失败"
exit 1
fi
else
log_error "未找到 Node.js 离线包: $node_tarball"
exit 1
fi
# [2] 安装 OpenClaw
local oc_tarball="$offline_dir/openclaw-deps.tar.gz"
if [ -f "$oc_tarball" ]; then
echo ""
echo "=== 安装 OpenClaw (离线) ==="
rm -rf "$OC_GLOBAL" 2>/dev/null
[ -d /overlay/upper ] && rm -rf "/overlay/upper${OC_GLOBAL}" 2>/dev/null
ensure_mkdir "$OC_GLOBAL"
tar xzf "$oc_tarball" -C "$OC_GLOBAL"
local oc_entry=$(find_oc_entry)
if [ -n "$oc_entry" ]; then
local oc_ver=$("$NODE_BIN" "$oc_entry" --version 2>/dev/null | tr -d '[:space:]')
log_info "OpenClaw v${oc_ver} 安装成功"
else
log_error "OpenClaw 安装验证失败"
exit 1
fi
else
log_error "未找到 OpenClaw 离线包: $oc_tarball"
exit 1
fi
# [3] 初始化
init_openclaw
echo ""
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║ ✅ 离线安装完成! ║"
echo "║ ║"
echo "║ 下一步: ║"
echo "║ uci set openclaw.main.enabled=1 ║"
echo "║ uci commit openclaw ║"
echo "║ /etc/init.d/openclaw enable ║"
echo "║ /etc/init.d/openclaw start ║"
echo "║ ║"
echo "║ 或在 LuCI → 服务 → OpenClaw 中启用 ║"
echo "╚══════════════════════════════════════════════════════════════╝"
}
# ── 主入口 ──
case "${1:-}" in
setup)
do_setup
;;
setup-offline)
do_setup_offline "$@"
;;
check)
do_check
;;
@@ -641,9 +744,10 @@ case "${1:-}" in
do_factory_reset
;;
*)
echo "用法: openclaw-env {setup|check|upgrade|node|factory-reset}"
echo "用法: openclaw-env {setup|setup-offline|check|upgrade|node|factory-reset}"
echo ""
echo " setup — 完整安装 (下载 Node.js + pnpm + OpenClaw)"
echo " setup-offline — 离线安装 (从本地文件安装,由 .run 安装器调用)"
echo " check — 检查环境状态"
echo " upgrade — 升级 OpenClaw 到最新版"
echo " node — 仅下载/更新 Node.js"

View File

@@ -1195,13 +1195,33 @@ configure_qq() {
echo -e " ${BOLD}🐧 QQ 机器人配置${NC}"
echo ""
# 检查 qqbot 插件是否已安装
# 检查 qqbot 插件是否已安装并正常加载
local plugin_installed=0
local plugin_blocked=0
local qqbot_ext_dir="${OC_STATE_DIR}/extensions/openclaw-qqbot"
if [ -n "$OC_ENTRY" ] && [ -x "$NODE_BIN" ]; then
local plugin_check=$(oc_cmd plugins list 2>/dev/null | grep -i "qqbot" | grep -i "loaded\|disabled")
if [ -n "$plugin_check" ]; then
local plugin_list=$(oc_cmd plugins list 2>&1)
# 在表格输出中查找含 qqbot 的行是否也包含 loaded
if echo "$plugin_list" | grep -i "qqbot" | grep -qi "loaded"; then
plugin_installed=1
echo -e " ${GREEN}✅ qqbot 插件已安装并加载${NC}"
elif echo "$plugin_list" | grep -qi "plugin not found.*openclaw-qqbot\|suspicious ownership"; then
# 插件目录存在但被阻止 (权限问题或 stale config)
if [ -d "$qqbot_ext_dir" ]; then
plugin_blocked=1
echo -e " ${YELLOW}⚠️ qqbot 插件已安装但未能正常加载${NC}"
echo -e " ${CYAN}正在修复插件目录权限...${NC}"
chown -R root:root "$qqbot_ext_dir" 2>/dev/null
echo -e " ${GREEN}✅ 权限已修复,重启 Gateway 后生效${NC}"
plugin_installed=1
fi
elif [ -d "$qqbot_ext_dir" ] && [ -f "${qqbot_ext_dir}/openclaw.plugin.json" ]; then
# 目录存在、有 plugin.json 但未出现在插件列表 — 修复权限
echo -e " ${YELLOW}⚠️ qqbot 插件目录存在但未能加载${NC}"
echo -e " ${CYAN}正在修复插件目录权限...${NC}"
chown -R root:root "$qqbot_ext_dir" 2>/dev/null
echo -e " ${GREEN}✅ 权限已修复${NC}"
plugin_installed=1
echo -e " ${GREEN}✅ qqbot 插件已安装${NC}"
fi
fi
@@ -1216,20 +1236,36 @@ configure_qq() {
local install_out
install_out=$(oc_cmd plugins install @tencent-connect/openclaw-qqbot@latest 2>&1)
local install_rc=$?
# 关键: 安装后立即修复插件目录权限为 root (OpenClaw 安全策略要求)
if [ -d "$qqbot_ext_dir" ]; then
chown -R root:root "$qqbot_ext_dir" 2>/dev/null
fi
if [ $install_rc -eq 0 ]; then
echo -e " ${GREEN}✅ qqbot 插件安装成功${NC}"
plugin_installed=1
else
echo -e " ${RED}❌ 插件安装失败 (exit: $install_rc)${NC}"
echo -e " ${DIM}${install_out}${NC}" | tail -5
# 安装命令返回非零,可能是因为 config invalid (死锁)
# 检查插件目录是否实际已存在 (说明下载成功但校验报错)
if [ -d "$qqbot_ext_dir" ] && [ -f "${qqbot_ext_dir}/openclaw.plugin.json" ]; then
echo -e " ${YELLOW}⚠️ 插件已下载但加载校验未通过 (exit: $install_rc)${NC}"
echo -e " ${CYAN}这通常是因为配置中已有 qqbot 设置但插件未被信任。${NC}"
echo -e " ${CYAN}已自动修复权限,重启 Gateway 后应能正常加载。${NC}"
plugin_installed=1
else
echo -e " ${RED}❌ 插件安装失败 (exit: $install_rc)${NC}"
echo -e " ${DIM}${install_out}${NC}" | tail -5
echo ""
echo -e " ${YELLOW}插件安装失败,但你仍然可以先配置 QQ 机器人参数。${NC}"
echo -e " ${YELLOW}稍后可手动安装: openclaw plugins install @tencent-connect/openclaw-qqbot@latest${NC}"
fi
echo ""
echo -e " ${YELLOW}请手动安装: openclaw plugins install @tencent-connect/openclaw-qqbot@latest${NC}"
return
fi
else
echo -e " ${YELLOW}已跳过插件安装。请先安装 qqbot 插件后再配置${NC}"
echo -e " ${CYAN}安装命令: openclaw plugins install @tencent-connect/openclaw-qqbot@latest${NC}"
return
echo -e " ${YELLOW}已跳过插件安装,继续配置 QQ 机器人参数${NC}"
echo -e " ${CYAN}稍后安装命令: openclaw plugins install @tencent-connect/openclaw-qqbot@latest${NC}"
echo ""
fi
fi
@@ -1483,7 +1519,7 @@ telegram_pairing() {
echo ""
echo -e " ${GREEN}╔══════════════════════════════════════════════════╗${NC}"
echo -e " ${GREEN}║ 请在 Telegram 中向 Bot 发送 /start ║${NC}"
echo -e " ${GREEN}║ 请在 Telegram 中向 Bot 发送 /start ${NC}"
echo -e " ${GREEN}║ 然后回到这里按回车,脚本自动检测配对请求 ║${NC}"
echo -e " ${GREEN}╚══════════════════════════════════════════════════╝${NC}"
echo ""
@@ -1999,26 +2035,39 @@ backup_restore_menu() {
echo -e " ${CYAN}将从以下备份恢复:${NC}"
echo -e " ${DIM}${latest}${NC}"
echo ""
echo -e " ${YELLOW}⚠️ 这会覆盖当前的 openclaw.json 配置${NC}"
echo -e " ${YELLOW}⚠️ 这会还原备份中的所有配置和数据文件到原路径${NC}"
prompt_with_default "确认恢复? (y/N)" "N" confirm_restore
if [ "$confirm_restore" = "y" ] || [ "$confirm_restore" = "Y" ]; then
# 备份当前配置
cp -f "$CONFIG_FILE" "${CONFIG_FILE}.pre-restore" 2>/dev/null
# 从 tar.gz 中提取 openclaw.json
local tmp_json="${CONFIG_FILE}.tmp"
# 验证备份中 openclaw.json 有效
local tmp_json="/tmp/oc-restore-check.json"
tar -xzf "$latest" --wildcards '*/openclaw.json' -O > "$tmp_json" 2>/dev/null
if [ -s "$tmp_json" ] && "$NODE_BIN" -e "JSON.parse(require('fs').readFileSync('${tmp_json}','utf8'))" 2>/dev/null; then
mv -f "$tmp_json" "$CONFIG_FILE"
chown openclaw:openclaw "$CONFIG_FILE" 2>/dev/null
echo -e " ${GREEN}✅ 配置已恢复!原配置已保存为 openclaw.json.pre-restore${NC}"
echo ""
prompt_with_default "是否重启服务使配置生效? (Y/n)" "Y" do_restart
if [ "$do_restart" != "n" ] && [ "$do_restart" != "N" ]; then
restart_gateway
fi
else
if [ ! -s "$tmp_json" ] || ! "$NODE_BIN" -e "JSON.parse(require('fs').readFileSync('${tmp_json}','utf8'))" 2>/dev/null; then
rm -f "$tmp_json"
echo -e " ${RED}❌ 备份中的配置文件无效,恢复已取消${NC}"
else
rm -f "$tmp_json"
# 备份当前配置
cp -f "$CONFIG_FILE" "${CONFIG_FILE}.pre-restore" 2>/dev/null
# 获取备份名前缀
local backup_name=$(tar -tzf "$latest" 2>/dev/null | head -1 | cut -d/ -f1)
if [ -z "$backup_name" ]; then
echo -e " ${RED}❌ 备份文件格式无法识别${NC}"
else
echo -e " ${DIM}正在还原文件...${NC}"
# 停止服务
/etc/init.d/openclaw stop >/dev/null 2>&1
sleep 2
# 提取 payload 到根目录 (还原到原始绝对路径)
tar -xzf "$latest" --strip-components=3 -C / "${backup_name}/payload/posix/" 2>&1
# 修复权限
chown -R openclaw:openclaw /opt/openclaw/data/.openclaw 2>/dev/null
echo -e " ${GREEN}✅ 配置和数据已完整恢复!原配置已保存为 openclaw.json.pre-restore${NC}"
echo ""
prompt_with_default "是否重启服务使配置生效? (Y/n)" "Y" do_restart
if [ "$do_restart" != "n" ] && [ "$do_restart" != "N" ]; then
restart_gateway
fi
fi
fi
else
echo -e " ${DIM}已取消${NC}"
@@ -2034,7 +2083,7 @@ main_menu() {
while true; do
echo ""
echo -e "${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}${NC} ${BOLD}OpenClaw AI Gateway — OpenWrt 配置管理${NC} ${GREEN}${NC}"
echo -e "${GREEN}${NC} ${BOLD}OpenClaw AI Gateway — OpenWrt 配置管理${NC} ${GREEN}${NC}"
echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e " ${CYAN}1)${NC} 📋 查看当前配置"