diff --git a/agents/sql/agent/workshop-skills/mysql-schema-sync/SKILL.md b/agents/sql/agent/workshop-skills/mysql-schema-sync/SKILL.md index 9bbb513..c0d2244 100644 --- a/agents/sql/agent/workshop-skills/mysql-schema-sync/SKILL.md +++ b/agents/sql/agent/workshop-skills/mysql-schema-sync/SKILL.md @@ -1,6 +1,6 @@ --- name: "mysql-schema-sync" -description: "MySQL 表结构同步最佳实践:跨环境同步 DDL,处理 CREATE/ALTER 失败场景" +description: "MySQL 表结构同步:使用 mysqldump 导出 DDL,生成审核脚本,处理跨环境同步的边界场景" --- # MySQL 表结构同步最佳实践 @@ -12,20 +12,23 @@ description: "MySQL 表结构同步最佳实践:跨环境同步 DDL,处理 C ## 核心原则 1. **表名必须带数据库前缀** - 如 `dmp_smdm.dmp_md_item_info`,因为生产实例有多个库 -2. **不暴露敏感信息** - 脚本中只写库名和表名,IP/密码用环境变量 +2. **不暴露敏感信息** - 脚本中不写密码,使用 `${MYSQL_PWD_SQL}` 环境变量 3. **先验证后执行** - 先 SELECT 确认表结构和数据量 4. **CREATE 优先于 ALTER** - 能新建不修改,减少冲突 +5. **脚本供审核,不直接执行** - 生成的 SQL 脚本需经审核后再执行 ## 脚本生成规范 ### 使用 mysqldump 导出结构 ```bash -mysqldump -h SOURCE_HOST -P PORT -u USER -p"PASSWORD" \ +mysqldump -h SOURCE_HOST -P PORT -u USER -p"${MYSQL_PWD_SQL}" \ --no-data --skip-lock-tables \ DB_NAME > db_struct.sql ``` +> 注意:密码从环境变量读取,不硬编码在脚本中。 + ### 脚本格式要求 ```sql @@ -55,10 +58,12 @@ scripts/YYYYMMDD/ ```bash for sql_file in database__*_struct.sql; do - mysql -h TARGET_HOST -u root -p"PASSWORD" -D database < "$sql_file" + mysql -h TARGET_HOST -u root -p"${MYSQL_PWD_SQL}" -D database < "$sql_file" done ``` +> 注意:上述命令仅用于生成执行脚本参考,实际执行前需经审核。 + ### ALTER TABLE(修改表) 1. **检查目标表是否存在** @@ -110,7 +115,7 @@ done 1. **执行前备份** ```bash - mysqldump -h TARGET_HOST -u root -p"PASSWORD" \ + mysqldump -h TARGET_HOST -u root -p"${MYSQL_PWD_SQL}" \ --no-data --routines --triggers \ database > backup_before_sync.sql ``` diff --git a/docs/agent-创建规范与自动化-设计.md b/docs/agent-创建规范与自动化-设计.md index 8be3906..ac85477 100644 --- a/docs/agent-创建规范与自动化-设计.md +++ b/docs/agent-创建规范与自动化-设计.md @@ -104,8 +104,9 @@ main 执行:bash ~/.openclaw/scripts/new-agent.sh reading 阅读 ```markdown ## 数据库规范 - 默认库:`{{AGENT_ID}}` —— 这就是你自己的库 -- 账号:`agent_{{AGENT_ID}}`;密码取环境变量 `DB_PASSWORD_{{AGENT_NAME}}` -- 连接:mysql -h 127.0.0.1 -u agent_{{AGENT_ID}} -p"${DB_PASSWORD_{{AGENT_NAME}}}" +- 账号:`agent_{{AGENT_ID}}` +- 连接(推荐):`~/.openclaw/scripts/db-conn.sh {{AGENT_ID}}`(交互式)或 `db-conn.sh {{AGENT_ID}} --sql "select database()"` +- 口令:由该脚本自动从 `~/.openclaw/.env` 读取(键名 `DB_PASSWORD_{{AGENT_NAME}}`),口令不会出现在命令行中 - 禁止:使用 root、使用 docker exec、访问其他 agent 的库、跨库写入 - 破坏性语句(DROP / TRUNCATE / 无条件 DELETE)必须先请示 ``` @@ -230,6 +231,7 @@ main 执行:bash ~/.openclaw/scripts/new-agent.sh reading 阅读 | 5 | 同机 3 个 `workspace-{juaner,tab,wellness}/db` 属主为 root → 这 3 个库自 2026-08-26 起**每天备份失败** | 已 `chown` 修复;备份脚本验收明确改为**不加 `sudo`**(生产路径是 yangxuan 的 crontab;用 sudo 跑正是该事故成因) | | 6 | `agents delete` 会连 workspace 一起删,但留下 `~/.openclaw/agents//` 空壳 | 清理流程需手工 `rm -rf`(已写入脚本注释与计划文档) | | 7 | 中文名含 `&` 时,调用侧若不加引号会被 shell 解析;实测已导致一次意外创建 | 已回灌进 `agent-provisioning` skill:**必须写成 ` '<中文名>'`** | +| 8 | **中文键名不可能作为环境变量暴露给 agent** —— 三条实测依据:(a) gateway 进程 `/proc//environ` 里只有 `MYSQL_PWD_ROOT`/`DB_PASSWORD_ROOT`,**没有** `DB_PASSWORD_<中文名>`;(b) service 的 `OPENCLAW_SERVICE_MANAGED_ENV_KEYS` 是白名单,只列 9 个键、不含 `DB_PASSWORD_*`,而键数随 agent 数量增长,维护白名单不现实;(c) 官方把凭据注入 agent 执行环境的机制 `openclaw secrets store --kind env` 要求名称匹配 `^[A-Z][A-Z0-9_]{0,127}$`(**纯大写 ASCII**),中文键名语法上就不合法 | ⇒ 以「环境变量」形式暴露中文键名**不可行**,改用统一入口 `~/.openclaw/scripts/db-conn.sh [--sql ""] [--print]`:按 id 反查 `agents.entries..name` → 读 `.env` 的 `DB_PASSWORD_<中文名>` → 经 `MYSQL_PWD` 环境变量注入 `docker exec`(口令不进 argv、不进 stdout;`--print` 只打印占位符)。已同步:11 个 `AGENTS.md`、`AGENTS.md.tpl`、`new-agent.sh` 汇总输出、本文 §5 示例。**§2 命名规范里的「密码变量 `DB_PASSWORD_<中文名>`」依然成立,但它的定位是 `.env` 内的存储键名,不再是 agent 的环境变量** | **审计日志格式(Task E 解析用)**: `[时间] id=… name=… user=… mode=create|reset-password selfcheck=… dry_run=…` diff --git a/scripts/agent-templates/AGENTS.md.tpl b/scripts/agent-templates/AGENTS.md.tpl index 671885e..a9bc79a 100644 --- a/scripts/agent-templates/AGENTS.md.tpl +++ b/scripts/agent-templates/AGENTS.md.tpl @@ -12,8 +12,8 @@ ## 数据库规范 - **默认库:** `{{AGENT_ID}}` —— 这就是我自己的库 - **账号:** `agent_{{AGENT_ID}}` -- **密码:** 环境变量 `DB_PASSWORD_{{AGENT_NAME}}` -- **连接:** `mysql -h 127.0.0.1 -u agent_{{AGENT_ID}} -p"${DB_PASSWORD_{{AGENT_NAME}}}" {{AGENT_ID}}` +- **连接(推荐):** `~/.openclaw/scripts/db-conn.sh {{AGENT_ID}}`(交互式)或 `~/.openclaw/scripts/db-conn.sh {{AGENT_ID}} --sql "select database()"` +- **口令:** 由该脚本自动从 `~/.openclaw/.env` 读取(键名 `DB_PASSWORD_{{AGENT_NAME}}`),口令不会出现在命令行中 - **禁止:** 使用 root、使用 `docker exec`、访问其他 agent 的库、跨库写入 - **建表前**先确认字段与索引;**破坏性语句**(DROP / TRUNCATE / 无条件 DELETE)必须先请示 diff --git a/scripts/db-conn.sh b/scripts/db-conn.sh new file mode 100755 index 0000000..77afd86 --- /dev/null +++ b/scripts/db-conn.sh @@ -0,0 +1,185 @@ +#!/usr/bin/env bash +# ============================================================================= +# db-conn.sh —— agent 访问自己专属 MySQL 库的唯一入口(统一 helper) +# +# 【用途】 +# agent 需要查/写自己的库(库名 = 自己的 agent id)时,一律通过本脚本。 +# 不要自己拼 mysql 命令,不要用 root,不要用 docker exec 直连。 +# +# 【为什么需要它】 +# 口令存放在 ~/.openclaw/.env,键名是中文的 DB_PASSWORD_<中文名>(便于人阅读)。 +# 实测确认:中文键名**无法**作为环境变量注入 agent 的执行环境,也无法交给 +# `openclaw secrets store --kind env` 托管(其名称语法限制为纯大写 ASCII)。 +# 依据见 ~/.openclaw/docs/agent-创建规范与自动化-设计.md 附录 A 第 8 条。 +# 因此由本脚本按 agent id 反查中文名 → 读 .env → 代入容器内的 docker MySQL。 +# +# 【用法】 +# db-conn.sh 交互式 mysql(已切到自己的库) +# db-conn.sh --sql "select 1" 执行一条 SQL,结果打到 stdout +# db-conn.sh --print 只打印等价命令(口令用占位符,可安全复制) +# db-conn.sh --help +# +# 【安全约定】 +# 1. 口令只通过环境变量 MYSQL_PWD 传给容器内的 mysql 客户端(客户端原生支持), +# 绝不出现在 argv/命令行,也绝不打印到 stdout/stderr,不落盘。 +# 2. 传参写成 `docker exec -e MYSQL_PWD`(**不带 =值**):docker 会从本脚本进程 +# 的环境里转发该变量。若写成 `-e MYSQL_PWD="$值"`,口令会进入 docker 进程的 +# argv,`ps -eo args` 可见(已实测),故不采用。 +# 3. 账号固定 agent_、库固定 ;脚本不提供切换账号/库的开关。 +# 4. --print 用占位符替换口令,输出可安全粘贴进聊天记录/工单。 +# 5. 本脚本不读取、也不使用任何 root 凭据。 +# +# 【退出码】 +# 0 成功 +# 2 用法/环境错误(参数缺失或非法、agent 不存在、中文名取不到、口令缺失) +# 其他 docker 或 mysql 的原始退出码 +# ============================================================================= +set -euo pipefail + +# —— 绝对路径与固定 PATH:不依赖登录 shell / rc 文件,cron 与 agent exec 都能跑 —— +export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" +OPENCLAW_ROOT="${OPENCLAW_ROOT:-/home/yangxuan/.openclaw}" +ENV_FILE="$OPENCLAW_ROOT/.env" +CONFIG_FILE="$OPENCLAW_ROOT/openclaw.json" +MYSQL_CONTAINER="mysql" + +usage() { + cat <<'USAGE' +用法: + db-conn.sh 交互式连接自己的库 + db-conn.sh --sql "" 执行一条 SQL 并输出结果 + db-conn.sh --print 只打印等价命令(口令以占位符显示) + db-conn.sh --help + + 即 openclaw.json 中 agents.entries 的键(如 main、juaner、sql)。 +账号固定为 agent_,库固定为 ;口令自动从 ~/.openclaw/.env +按中文键名 DB_PASSWORD_<中文名> 读取,不会出现在命令行里。 +USAGE +} + +# —— 打印用:把 SQL 包成可直接复制的 shell 字面量(优先单引号,含单引号时退回 %q)—— +quote_sql() { + local s="$1" + if [[ "$s" != *"'"* ]]; then + printf "'%s'" "$s" + else + printf '%q' "$s" + fi +} + +# —— ⓪ 参数解析 —— +AGENT_ID="" +SQL="" +PRINT_ONLY=0 + +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) usage; exit 0 ;; + --print) PRINT_ONLY=1; shift ;; + --sql) + [[ $# -ge 2 ]] || { echo "错误:--sql 后面缺少 SQL 语句" >&2; usage >&2; exit 2; } + SQL="$2"; shift 2 ;; + --sql=*) SQL="${1#--sql=}"; shift ;; + --*) echo "错误:未知参数 $1" >&2; usage >&2; exit 2 ;; + *) + if [[ -z "$AGENT_ID" ]]; then + AGENT_ID="$1"; shift + else + echo "错误:多余的参数 $1(只接受一个 )" >&2; usage >&2; exit 2 + fi ;; + esac +done + +[[ -n "$AGENT_ID" ]] || { echo "错误:缺少 " >&2; usage >&2; exit 2; } +[[ "$AGENT_ID" =~ ^[a-z][a-z0-9-]{0,23}$ ]] || { + echo "错误:agent_id 非法(只允许小写字母开头、[a-z0-9-]、最长 24 字符):$AGENT_ID" >&2 + exit 2 +} + +DB_USER="agent_$AGENT_ID" +DB_NAME="$AGENT_ID" + +# —— ① 环境依赖 —— +command -v python3 >/dev/null 2>&1 || { echo "错误:找不到 python3(本脚本用它解析 $CONFIG_FILE)" >&2; exit 2; } +command -v docker >/dev/null 2>&1 || { echo "错误:找不到 docker 命令" >&2; exit 2; } +[[ -f "$CONFIG_FILE" ]] || { echo "错误:找不到配置文件 $CONFIG_FILE" >&2; exit 2; } +[[ -f "$ENV_FILE" ]] || { echo "错误:找不到口令文件 $ENV_FILE" >&2; exit 2; } + +# —— ② agent_id → 中文名(agents.entries..name;取不到即报错)—— +AGENT_NAME="" +NAME_RC=0 +AGENT_NAME="$(python3 - "$CONFIG_FILE" "$AGENT_ID" <<'PY' +import json, sys + +cfg_path, agent_id = sys.argv[1], sys.argv[2] +try: + with open(cfg_path, encoding="utf-8") as fh: + cfg = json.load(fh) +except Exception as exc: + sys.stderr.write("读取 %s 失败:%s\n" % (cfg_path, exc)) + sys.exit(3) + +entries = ((cfg.get("agents") or {}).get("entries")) or {} +entry = entries.get(agent_id) +if not isinstance(entry, dict): + sys.exit(4) + +# 主键是 name;个别条目若只有 identity.name,则兜底取它,避免 helper 对拓扑差异敏感 +name = str(entry.get("name") or "").strip() +if not name and isinstance(entry.get("identity"), dict): + name = str(entry["identity"].get("name") or "").strip() +if not name: + sys.exit(5) +sys.stdout.write(name) +PY +)" || NAME_RC=$? + +case "$NAME_RC" in + 0) ;; + 4) echo "错误:agent '$AGENT_ID' 不在 $CONFIG_FILE 的 agents.entries 中" >&2; exit 2 ;; + 5) echo "错误:agent '$AGENT_ID' 在配置里没有 name(中文名),无法定位其口令键" >&2; exit 2 ;; + *) echo "错误:解析 $CONFIG_FILE 失败(python3 退出码 $NAME_RC)" >&2; exit 2 ;; +esac + +# —— ③ 中文名 → 口令(.env 内键名 DB_PASSWORD_<中文名>)—— +PWD_KEY="DB_PASSWORD_$AGENT_NAME" +PWD_VALUE="" +PWD_VALUE="$( + awk -v k="$PWD_KEY" 'index($0, k "=") == 1 { print substr($0, length(k) + 2); exit }' "$ENV_FILE" +)" +# 去掉行尾 CR 与成对引号(.env 可能被编辑器写坏) +PWD_VALUE="${PWD_VALUE%$'\r'}" +case "$PWD_VALUE" in + \"*\") PWD_VALUE="${PWD_VALUE:1:${#PWD_VALUE}-2}" ;; + \'*\') PWD_VALUE="${PWD_VALUE:1:${#PWD_VALUE}-2}" ;; +esac +if [[ -z "$PWD_VALUE" ]]; then + echo "错误:$ENV_FILE 里没有 $PWD_KEY(agent '$AGENT_ID'/中文名 '$AGENT_NAME')" >&2 + echo " 该 agent 可能尚未纳入 —— 请联系杨轩用 new-agent.sh 补建/纳入后重试" >&2 + exit 2 +fi + +# —— ④ --print:只打印等价命令,口令用占位符(绝不打印真实值)—— +if [[ "$PRINT_ONLY" == "1" ]]; then + if [[ -n "$SQL" ]]; then + printf "MYSQL_PWD='<从 .env 读取:%s>' docker exec -e MYSQL_PWD %s mysql -u%s -N -B -e %s %s\n" \ + "$PWD_KEY" "$MYSQL_CONTAINER" "$DB_USER" "$(quote_sql "$SQL")" "$DB_NAME" + else + # 交互式:本地有 TTY 才能 -it(与下面实际执行时的判定保持一致) + if [[ -t 0 && -t 1 ]]; then TTY_FLAGS="-it"; else TTY_FLAGS="-i"; fi + printf "MYSQL_PWD='<从 .env 读取:%s>' docker exec %s -e MYSQL_PWD %s mysql -u%s %s\n" \ + "$PWD_KEY" "$TTY_FLAGS" "$MYSQL_CONTAINER" "$DB_USER" "$DB_NAME" + fi + exit 0 +fi + +# —— ⑤ 连接:口令经 MYSQL_PWD 环境变量转发(不进 argv、不进 stdout)—— +if [[ -n "$SQL" ]]; then + MYSQL_PWD="$PWD_VALUE" docker exec -e MYSQL_PWD "$MYSQL_CONTAINER" \ + mysql -u"$DB_USER" -N -B -e "$SQL" "$DB_NAME" +else + if [[ -t 0 && -t 1 ]]; then TTY_FLAGS="-it"; else TTY_FLAGS="-i"; fi + echo "→ 已连接:库 $DB_NAME,账号 $DB_USER(输入 exit 或按 Ctrl-D 退出)" >&2 + MYSQL_PWD="$PWD_VALUE" docker exec $TTY_FLAGS -e MYSQL_PWD "$MYSQL_CONTAINER" \ + mysql -u"$DB_USER" "$DB_NAME" +fi diff --git a/scripts/new-agent.sh b/scripts/new-agent.sh index e5742e7..de13eaa 100755 --- a/scripts/new-agent.sh +++ b/scripts/new-agent.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash # 新建 OpenClaw agent:建库 → 建号 → 授权 → 写 .env → 创建 agent → 渲染中文模板 → 自检 +# 另含 --reset-password(重置既有账号密码)与 --adopt(为既有 agent 补建缺失的库/账号)两个模式 set -euo pipefail ENV_FILE="$HOME/.openclaw/.env" @@ -13,19 +14,21 @@ MYSQL_CONTAINER="mysql" TEMPLATES=(IDENTITY SOUL AGENTS MEMORY USER) TEMPLATE_LIST="$(printf '%s.md ' "${TEMPLATES[@]}")" -usage() { echo "用法: new-agent.sh <中文名> [--dry-run] [--reset-password]"; } +usage() { echo "用法: new-agent.sh <中文名> [--dry-run] [--reset-password] [--adopt]"; } # —— ⓪ 参数解析(参数不足直接给用法,不当作未知参数)—— [[ $# -ge 2 ]] || { usage; exit 2; } AGENT_ID="$1"; AGENT_NAME="$2"; shift 2 -DRY_RUN=0; RESET_PASSWORD=0 +DRY_RUN=0; RESET_PASSWORD=0; ADOPT=0 for arg in "$@"; do case "$arg" in --dry-run) DRY_RUN=1 ;; --reset-password) RESET_PASSWORD=1 ;; + --adopt) ADOPT=1 ;; *) echo "未知参数: $arg" >&2; usage; exit 2 ;; esac done +[[ $((RESET_PASSWORD + ADOPT)) -le 1 ]] || { echo "--reset-password 与 --adopt 互斥,不能同时使用" >&2; exit 2; } # —— ① 入参校验 —— [[ -n "$AGENT_ID" && -n "$AGENT_NAME" ]] || { usage; exit 2; } @@ -64,6 +67,12 @@ WS_EXISTS=$([[ -d "$WORKSPACE" ]] && echo 1 || echo 0) if [[ "$RESET_PASSWORD" == "1" ]]; then [[ "$USER_EXISTS" == "1" ]] || { echo "账号 $DB_USER 不存在,无法重置密码"; exit 1; } +elif [[ "$ADOPT" == "1" ]]; then + # 纳入模式:只补「库/账号缺失」的存量 agent,跳过 创建 agent / 模板渲染 / set-identity。 + # 库或账号已存在时仍拒绝 —— 保持与 create 模式一致的幂等语义,避免覆盖既有数据。 + [[ "$DB_EXISTS" == "0" ]] || { echo "❌ 库 $AGENT_ID 已存在 —— --adopt 只补建缺失的库/账号;库已存在请改用 new-agent.sh --reset-password 或手工授权"; exit 1; } + [[ "$USER_EXISTS" == "0" ]] || { echo "❌ 账号 $DB_USER 已存在 —— --adopt 拒绝;如需重置密码请用 --reset-password"; exit 1; } + [[ "$AGENT_EXISTS" == "1" || "$WS_EXISTS" == "1" ]] || { echo "❌ agent 条目与目录 $WORKSPACE 都不存在 —— 这属于新建场景,请去掉 --adopt"; exit 1; } else [[ "$DB_EXISTS" == "0" ]] || { echo "❌ 库 $AGENT_ID 已存在 —— 已存在请使用 --reset-password,或改用 new-agent.sh 管理"; exit 1; } [[ "$USER_EXISTS" == "0" ]] || { echo "❌ 账号 $DB_USER 已存在 —— 请使用 --reset-password"; exit 1; } @@ -80,7 +89,9 @@ SQL_CREATE_USER="CREATE USER '$DB_USER'@'%' IDENTIFIED BY '$NEW_PWD';" SQL_ALTER_USER="ALTER USER '$DB_USER'@'%' IDENTIFIED BY '$NEW_PWD';" SQL_GRANT="GRANT ALL PRIVILEGES ON \`$AGENT_ID\`.* TO '$DB_USER'@'%';" -if [[ "$RESET_PASSWORD" == "1" ]]; then MODE="reset-password"; else MODE="create"; fi +if [[ "$RESET_PASSWORD" == "1" ]]; then MODE="reset-password" +elif [[ "$ADOPT" == "1" ]]; then MODE="adopt" +else MODE="create"; fi if [[ "$DRY_RUN" == "1" ]]; then echo "[dry-run] 模式:$MODE" @@ -98,6 +109,8 @@ if [[ "$DRY_RUN" == "1" ]]; then echo "[dry-run] 将写入 $ENV_FILE:$PASSWORD_VAR=<32位随机>" if [[ "$MODE" == "reset-password" ]]; then echo "[dry-run] 将跳过:openclaw agents add / 模板渲染 / set-identity(agent 与 workspace 保持不变)" + elif [[ "$MODE" == "adopt" ]]; then + echo "[dry-run] 将跳过:openclaw agents add / 模板渲染 / set-identity(agent 条目已存在=$AGENT_EXISTS,目录已存在=$WS_EXISTS,不覆盖既有内容)" else echo "[dry-run] 将创建 workspace:$WORKSPACE" echo "[dry-run] 将执行:openclaw agents add $AGENT_ID --workspace $WORKSPACE --non-interactive" @@ -118,6 +131,7 @@ if [[ "$MODE" == "reset-password" ]]; then fi mysql_root "$SQL_ALTER_USER" >/dev/null else + # create 与 adopt 共用:建库 + 建号(adopt 已在上面的检查中确认两者都不存在) mysql_root "$SQL_CREATE_DB" >/dev/null mysql_root "$SQL_CREATE_USER" >/dev/null fi @@ -141,6 +155,11 @@ if [[ "$MODE" == "reset-password" ]]; then # —— 重置模式:跳过 ⑥ 创建 agent / ⑦ 模板渲染 / ⑧ set-identity —— # agent 条目、workspace 与模板都已存在,重复执行只会失败或覆盖既有内容。 echo "ℹ️ 重置模式:跳过 创建 agent / 模板渲染 / set-identity" +elif [[ "$MODE" == "adopt" ]]; then + # —— 纳入模式:同样跳过 ⑥⑦⑧ —— + # agent 条目与 workspace(含既有 AGENTS.md 等文档)都已存在, + # 本模式只负责「建库 → 建账号 → 授权 → 写 .env」,绝不触碰既有 workspace 内容。 + echo "ℹ️ 纳入模式(adopt):跳过 创建 agent / 模板渲染 / set-identity(不覆盖既有 workspace 内容)" else # —— ⑥ 创建 agent —— export NVM_DIR="$HOME/.nvm"; . "$NVM_DIR/nvm.sh"; nvm use 26 >/dev/null 2>&1 @@ -191,6 +210,9 @@ printf '[%s] id=%s name=%s user=%s mode=%s selfcheck=%s dry_run=%s\n' \ if [[ "$MODE" == "reset-password" ]]; then echo "" echo "✅ 已重置 agent 密码:$AGENT_NAME($AGENT_ID)" +elif [[ "$MODE" == "adopt" ]]; then + echo "" + echo "✅ 已为既有 agent 补建专属库与专用账号:$AGENT_NAME($AGENT_ID)" else echo "" echo "✅ 已创建 agent:$AGENT_NAME($AGENT_ID)" @@ -202,5 +224,6 @@ USER=$DB_USER PASSWORD_ENV=$PASSWORD_VAR WORKSPACE=$WORKSPACE 自检=$SELFCHECK +连接:$OPENCLAW_ROOT/scripts/db-conn.sh $AGENT_ID (交互式;或加 --sql "" 执行单条 SQL;口令自动从 .env 读取,不进命令行) EOF [[ "$SELFCHECK" == "ok" ]] || { echo "⚠️ 自检失败:请检查授权"; exit 1; } diff --git a/workspace-finances/AGENTS.md b/workspace-finances/AGENTS.md index 3061668..0db87c4 100644 --- a/workspace-finances/AGENTS.md +++ b/workspace-finances/AGENTS.md @@ -7,6 +7,13 @@ 2. 读取 `MEMORY.md` 获得历史上下文 3. 检查并初始化 MySQL 数据库 finances +## 数据库规范(专用账号) + +- 默认库:`finances`;账号:`agent_finances` +- 连接(推荐):`~/.openclaw/scripts/db-conn.sh finances`(交互式)或 `~/.openclaw/scripts/db-conn.sh finances --sql "select database()"` +- 该脚本自动从 `~/.openclaw/.env` 读取本 agent 的专属口令(键名 `DB_PASSWORD_理财`),口令不会出现在命令行中 +- 禁止使用 root、禁止 docker exec、禁止访问其他 agent 的库 + ## 数据库初始化 SQL(首次运行自动执行) ```sql diff --git a/workspace-fitness/AGENTS.md b/workspace-fitness/AGENTS.md index e64da98..cf3b9cd 100644 --- a/workspace-fitness/AGENTS.md +++ b/workspace-fitness/AGENTS.md @@ -173,7 +173,10 @@ ORDER BY record_date ASC; ## 数据存储 -- MySQL: root/5gynj20J, database: fitness +- 默认库:`fitness`;账号:`agent_fitness` +- 连接(推荐):`~/.openclaw/scripts/db-conn.sh fitness`(交互式)或 `~/.openclaw/scripts/db-conn.sh fitness --sql "select database()"` +- 该脚本自动从 `~/.openclaw/.env` 读取本 agent 的专属口令(键名 `DB_PASSWORD_健康`),口令不会出现在命令行中 +- 禁止使用 root、禁止 docker exec、禁止访问其他 agent 的库 - 所有健康数据本地存储 ## 数据库表结构概览 diff --git a/workspace-juaner/AGENTS.md b/workspace-juaner/AGENTS.md index f9fdc2b..ed15326 100644 --- a/workspace-juaner/AGENTS.md +++ b/workspace-juaner/AGENTS.md @@ -8,3 +8,10 @@ - `data/` — 记账数据、待办数据 - `jinshu/` — 杨锦书知识库(儿子成长档案) - `MEMORY.md` — 长期记忆(王芳的重要信息) + +## 数据库规范(专用账号) + +- 默认库:`juaner`;账号:`agent_juaner` +- 连接(推荐):`~/.openclaw/scripts/db-conn.sh juaner`(交互式)或 `~/.openclaw/scripts/db-conn.sh juaner --sql "select database()"` +- 该脚本自动从 `~/.openclaw/.env` 读取本 agent 的专属口令(键名 `DB_PASSWORD_卷儿`),口令不会出现在命令行中 +- 禁止使用 root、禁止 docker exec、禁止访问其他 agent 的库 diff --git a/workspace-note/AGENTS.md b/workspace-note/AGENTS.md index 508ec43..4a0343f 100644 --- a/workspace-note/AGENTS.md +++ b/workspace-note/AGENTS.md @@ -45,3 +45,10 @@ - 遇到不确定分类的文档 → 放入 `000-Inbox`,并在回复中说明 - 遇到重名 → 主文件优先,冲突文件加 `1` 后缀或日期,不覆盖 - 不发送任何内容到外部,只在本地笔记库内操作 + +## 数据库规范(专用账号) + +- 默认库:`note`;账号:`agent_note` +- 连接(推荐):`~/.openclaw/scripts/db-conn.sh note`(交互式)或 `~/.openclaw/scripts/db-conn.sh note --sql "select database()"` +- 该脚本自动从 `~/.openclaw/.env` 读取本 agent 的专属口令(键名 `DB_PASSWORD_笔记`),口令不会出现在命令行中 +- 禁止使用 root、禁止 docker exec、禁止访问其他 agent 的库 diff --git a/workspace-pbs/AGENTS.md b/workspace-pbs/AGENTS.md index db15224..9870ca1 100644 --- a/workspace-pbs/AGENTS.md +++ b/workspace-pbs/AGENTS.md @@ -150,3 +150,10 @@ Add whatever helps you do your job. This is your cheat sheet. - `proxmox-backup-manager datastore list` - `proxmox-backup-manager task list` - `df -h`, `ls`, `cat` 等查询类命令 + +## 数据库规范(专用账号) + +- 默认库:`pbs`;账号:`agent_pbs` +- 连接(推荐):`~/.openclaw/scripts/db-conn.sh pbs`(交互式)或 `~/.openclaw/scripts/db-conn.sh pbs --sql "select database()"` +- 该脚本自动从 `~/.openclaw/.env` 读取本 agent 的专属口令(键名 `DB_PASSWORD_PBS备份`),口令不会出现在命令行中 +- 禁止使用 root、禁止 docker exec、禁止访问其他 agent 的库 diff --git a/workspace-resume/AGENTS.md b/workspace-resume/AGENTS.md index fd0d03f..76277a5 100644 --- a/workspace-resume/AGENTS.md +++ b/workspace-resume/AGENTS.md @@ -184,11 +184,18 @@ - `混合方案指南.md` - 混合方案说明 - **命名格式**:`YYYY-Www-周报.md`(如 `2026-W31-周报.md`) +## 数据库规范(专用账号) + +- 默认库:`resume`;账号:`agent_resume` +- 连接(推荐):`~/.openclaw/scripts/db-conn.sh resume`(交互式)或 `~/.openclaw/scripts/db-conn.sh resume --sql "select database()"` +- 该脚本自动从 `~/.openclaw/.env` 读取本 agent 的专属口令(键名 `DB_PASSWORD_简历`),口令不会出现在命令行中 +- 禁止使用 root、禁止 docker exec、禁止访问其他 agent 的库 + ## MySQL 周报数据中枢(2026-08-27 建立) 方案 A:**SQLite 做本地归档,MySQL resume 库做统一数据中枢**(供月度/年度总结、OKR 分析)。 -- **MySQL 连接**:`127.0.0.1:3306`,用户 `root`,库 `resume`,密码存 `.env` 键 `MYSQL_PWD` +- **MySQL 连接**:`127.0.0.1:3306`,用户 `agent_resume`,库 `resume`;连接方式统一用 `~/.openclaw/scripts/db-conn.sh resume`(口令由脚本从 `~/.openclaw/.env` 读取,不进命令行) - **三张周报表**(在 `resume` 库): - `weekly_reports` — 主表(year、week_number、project、start_date/end_date、main_task、has_problems) - `weekly_report_daily` — 每日明细(report_id、day_of_week、work_date、work_items) diff --git a/workspace-sql/AGENTS.md b/workspace-sql/AGENTS.md index 5e9013e..2699311 100644 --- a/workspace-sql/AGENTS.md +++ b/workspace-sql/AGENTS.md @@ -49,6 +49,26 @@ - **技能 (sql-toolkit) 也遵循此默认**:未指定环境时指向 VPS - **需要切换环境时明确告知**:本地、备用机、或者特定库 +## 数据库规范(本地私有库) + +- 默认库:`sql`;账号:`agent_sql` +- 连接(推荐):`~/.openclaw/scripts/db-conn.sh sql`(交互式)或 `~/.openclaw/scripts/db-conn.sh sql --sql "select database()"` +- 该脚本自动从 `~/.openclaw/.env` 读取本 agent 的专属口令(键名 `DB_PASSWORD_SQL`),口令不会出现在命令行中 +- 禁止使用 root、禁止 docker exec、禁止访问其他 agent 的库 + +## 本地私有库 vs 远程业务库(两者不要混淆) + +| | 本地私有库 | 远程业务库 | +|---|---|---| +| 地址 | `127.0.0.1:3306`(本机 docker MySQL) | `101.34.227.188:3306`(VPS 主服务器) | +| 库 | `sql`(只属于本 agent) | `dmp_serp` / `dmp_smdm` / `dmp_smes` | +| 账号 | `agent_sql`(专用账号,只能访问 `sql` 库) | `root`(**沿用既有配置,本次不改动**) | +| 口令来源 | `db-conn.sh` 自动读 `.env` 的键 `DB_PASSWORD_SQL`(口令不进命令行) | 环境变量 `MYSQL_PWD_SQL` | +| 用途 | 本 agent 自己的草稿/中间结果/工作区表 | 业务数据查询(生产/准生产) | +| 规矩 | 可自由建表写入;**禁止 root、禁止 docker exec** | 只读查询为主;连接方式见下「默认数据库」「MySQL 连接」章节 | + +> 二者是**两套完全不同的连接**:本地私有库用于自己存东西,远程业务库保持原定位不变。 + ## 相关 - [Agent workspace](/concepts/agent-workspace) diff --git a/workspace-tab/AGENTS.md b/workspace-tab/AGENTS.md index 3018efb..661a4cd 100644 --- a/workspace-tab/AGENTS.md +++ b/workspace-tab/AGENTS.md @@ -23,6 +23,13 @@ Do not manually reread startup files unless: **必须读 skill**:`skills/tab/SKILL.md`——里面有连接方式、表结构、SQL 模板、favicon 获取逻辑。动手前先读它。 +## 数据库规范(专用账号) + +- 默认库:`tab`;账号:`agent_tab` +- 连接(推荐):`~/.openclaw/scripts/db-conn.sh tab`(交互式)或 `~/.openclaw/scripts/db-conn.sh tab --sql "select database()"` +- 该脚本自动从 `~/.openclaw/.env` 读取本 agent 的专属口令(键名 `DB_PASSWORD_导航页`),口令不会出现在命令行中 +- 禁止使用 root、禁止 docker exec、禁止访问其他 agent 的库 + ## Memory You wake up fresh each session. Files are your continuity: diff --git a/workspace-travel/AGENTS.md b/workspace-travel/AGENTS.md index e578023..3a34e8f 100644 --- a/workspace-travel/AGENTS.md +++ b/workspace-travel/AGENTS.md @@ -251,3 +251,10 @@ This is a starting point. Add your own conventions, style, and rules as you figu ## Related - [Default AGENTS.md](/reference/AGENTS.default) + +## 数据库规范(专用账号) + +- 默认库:`travel`;账号:`agent_travel` +- 连接(推荐):`~/.openclaw/scripts/db-conn.sh travel`(交互式)或 `~/.openclaw/scripts/db-conn.sh travel --sql "select database()"` +- 该脚本自动从 `~/.openclaw/.env` 读取本 agent 的专属口令(键名 `DB_PASSWORD_旅行`),口令不会出现在命令行中 +- 禁止使用 root、禁止 docker exec、禁止访问其他 agent 的库 diff --git a/workspace-wellness/AGENTS.md b/workspace-wellness/AGENTS.md index cd959bc..7c95377 100644 --- a/workspace-wellness/AGENTS.md +++ b/workspace-wellness/AGENTS.md @@ -131,3 +131,10 @@ This is a starting point. Add your own conventions, style, and rules as you figu - [Default AGENTS.md](/reference/AGENTS.default) - [Scheduled tasks vs heartbeat](/automation#scheduled-tasks-cron-vs-heartbeat) - [Heartbeat](/gateway/heartbeat) + +## 数据库规范(专用账号) + +- 默认库:`wellness`;账号:`agent_wellness` +- 连接(推荐):`~/.openclaw/scripts/db-conn.sh wellness`(交互式)或 `~/.openclaw/scripts/db-conn.sh wellness --sql "select database()"` +- 该脚本自动从 `~/.openclaw/.env` 读取本 agent 的专属口令(键名 `DB_PASSWORD_放松保健`),口令不会出现在命令行中 +- 禁止使用 root、禁止 docker exec、禁止访问其他 agent 的库 diff --git a/workspace/AGENTS.md b/workspace/AGENTS.md index a5400f9..6aeae16 100644 --- a/workspace/AGENTS.md +++ b/workspace/AGENTS.md @@ -38,6 +38,13 @@ 禁止自行拼 SQL、禁止用 `mysql`/`docker exec` 建库、禁止为建库读取任何 root 凭据、禁止手工创建 `workspace-*` 或手改 agents 配置。 - **数据库红线**:每个 agent 只能访问自己的库(库名 = 自己的 agent id),账号为 `agent_`;禁止使用 root、禁止跨库写入。 +## 数据库规范(专用账号) + +- 默认库:`main`;账号:`agent_main` +- 连接(推荐):`~/.openclaw/scripts/db-conn.sh main`(交互式)或 `~/.openclaw/scripts/db-conn.sh main --sql "select database()"` +- 该脚本自动从 `~/.openclaw/.env` 读取本 agent 的专属口令(键名 `DB_PASSWORD_助手`),口令不会出现在命令行中 +- 禁止使用 root、禁止 docker exec、禁止访问其他 agent 的库 + ## 外部 vs 内部 **可以自由执行的操作:** 文件读取、网络搜索、日历查看、工作区内工作