feat(agent-db): 引入 db-conn.sh 统一数据库入口,各 agent 改用专用账号

- 新增 scripts/db-conn.sh:按 agent id 反查中文名,读 .env 后经 MYSQL_PWD 转发给 docker exec,口令不进 argv/stdout,--print 只输出占位符
- new-agent.sh 新增 --adopt 模式(为既有 agent 补建库/账号),与 --reset-password 互斥
- AGENTS.md.tpl 与 11 个 workspace-*/AGENTS.md 改用 db-conn.sh,禁用 root 与 docker exec 直连
- mysql-schema-sync 技能改用 MYSQL_PWD_SQL 环境变量,不再硬编码密码
- 设计文档补附录 A 第 8 条:中文键名无法注入 agent 环境的三条实测依据
This commit is contained in:
2026-09-16 11:30:55 +08:00
parent 75d3aa8067
commit 31c9958741
16 changed files with 315 additions and 14 deletions
+26 -3
View File
@@ -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 <id> <中文名> [--dry-run] [--reset-password]"; }
usage() { echo "用法: new-agent.sh <id> <中文名> [--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-identityagent 与 workspace 保持不变)"
elif [[ "$MODE" == "adopt" ]]; then
echo "[dry-run] 将跳过:openclaw agents add / 模板渲染 / set-identityagent 条目已存在=$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>" 执行单条 SQL;口令自动从 .env 读取,不进命令行)
EOF
[[ "$SELFCHECK" == "ok" ]] || { echo "⚠️ 自检失败:请检查授权"; exit 1; }