|
|
@@ -58,24 +58,163 @@ ask() {
|
|
|
printf -v "${__var}" '%s' "${__ans}"
|
|
|
}
|
|
|
|
|
|
-# 提示输入密码(不回显):ask_secret VAR "提示" "默认值"
|
|
|
-ask_secret() {
|
|
|
- local __var="$1" __prompt="$2" __default="${3:-}" __ans
|
|
|
- read -r -s -p "$(echo -e "${c_bold}${__prompt}${c_reset}${__default:+ [回车用默认]}: ")" __ans
|
|
|
- echo
|
|
|
- __ans="${__ans:-${__default}}"
|
|
|
+# 必填输入(非空,否则循环重试):ask_required VAR "提示"
|
|
|
+ask_required() {
|
|
|
+ local __var="$1" __prompt="$2" __ans
|
|
|
+ while :; do
|
|
|
+ read -r -p "$(echo -e "${c_bold}${__prompt}${c_reset}: ")" __ans
|
|
|
+ [[ -n "${__ans}" ]] && break
|
|
|
+ warn "不能为空,请重新输入。"
|
|
|
+ done
|
|
|
printf -v "${__var}" '%s' "${__ans}"
|
|
|
}
|
|
|
|
|
|
-# 强制输入密码(不回显、无默认,必须非空且两次一致):ask_secret_required VAR "提示"
|
|
|
+# 序号选择(限定合法值,否则循环重试):ask_choice VAR "提示" "默认" "1 2 3"
|
|
|
+ask_choice() {
|
|
|
+ local __var="$1" __prompt="$2" __default="$3" __valid="$4" __ans __v
|
|
|
+ while :; do
|
|
|
+ read -r -p "$(echo -e "${c_bold}${__prompt}${c_reset} [${__default}]: ")" __ans
|
|
|
+ __ans="${__ans:-${__default}}"
|
|
|
+ for __v in ${__valid}; do
|
|
|
+ [[ "${__ans}" == "${__v}" ]] && { printf -v "${__var}" '%s' "${__ans}"; return 0; }
|
|
|
+ done
|
|
|
+ warn "无效选择:${__ans},请输入 [${__valid// /\/}] 之一。"
|
|
|
+ done
|
|
|
+}
|
|
|
+
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
+# 模块小结 + 回改驱动器
|
|
|
+# 用法:edit_module "模块标题" "VAR|提示|类型|默认" ...
|
|
|
+# 类型:plain(普通,带默认) | required(必填非空) | optional(可空)
|
|
|
+# secret(密码,带默认,回车用默认) | secret_required(必填密码)
|
|
|
+# 交互:先逐项询问 → 显示小结 → 输编号改单项 / r 全部重来 / 回车确认
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
+# 单字段询问:按类型调用相应输入函数
|
|
|
+_ask_field() {
|
|
|
+ local var="$1" prompt="$2" type="$3" default="$4"
|
|
|
+ case "${type}" in
|
|
|
+ plain) ask "${var}" "${prompt}" "${default}" ;;
|
|
|
+ required) ask_required "${var}" "${prompt}" ;;
|
|
|
+ optional) ask "${var}" "${prompt}" "${default}" ;;
|
|
|
+ secret) ask_secret "${var}" "${prompt}" "${default}" ;;
|
|
|
+ secret_required) ask_secret_required "${var}" "${prompt}" ;;
|
|
|
+ *) ask "${var}" "${prompt}" "${default}" ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+# 小结里字段值的展示(密码做掩码;secret 用默认时显默认明文)
|
|
|
+_display_field() {
|
|
|
+ local type="$3" default="$4" val="${!1}"
|
|
|
+ case "${type}" in
|
|
|
+ secret)
|
|
|
+ if [[ -n "${val}" && "${val}" == "${default}" ]]; then
|
|
|
+ printf '%s(默认)' "${val}" # 用默认 → 明文显示
|
|
|
+ elif [[ -n "${val}" ]]; then
|
|
|
+ printf '******' # 手动输入 → 掩码
|
|
|
+ else
|
|
|
+ printf '(空)'
|
|
|
+ fi
|
|
|
+ ;;
|
|
|
+ secret_required)
|
|
|
+ [[ -n "${val}" ]] && printf '******' || printf '(未设置)'
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ [[ -n "${val}" ]] && printf '%s' "${val}" || printf '(空)'
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+edit_module() {
|
|
|
+ local mtitle="$1"; shift
|
|
|
+ local specs=("$@")
|
|
|
+ local n="${#specs[@]}"
|
|
|
+ local i spec var prompt type default sel
|
|
|
+
|
|
|
+ # 首轮逐项询问
|
|
|
+ title "${mtitle}"
|
|
|
+ for spec in "${specs[@]}"; do
|
|
|
+ IFS='|' read -r var prompt type default <<<"${spec}"
|
|
|
+ _ask_field "${var}" "${prompt}" "${type}" "${default}"
|
|
|
+ done
|
|
|
+
|
|
|
+ # 小结 + 回改循环
|
|
|
+ while :; do
|
|
|
+ echo
|
|
|
+ echo -e "${c_bold}${mtitle} — 配置小结:${c_reset}"
|
|
|
+ for ((i=0; i<n; i++)); do
|
|
|
+ IFS='|' read -r var prompt type default <<<"${specs[i]}"
|
|
|
+ printf " %d) %-28s = %s\n" "$((i+1))" "${prompt}" "$(_display_field "${var}" "${prompt}" "${type}" "${default}")"
|
|
|
+ done
|
|
|
+ read -r -p "$(echo -e "操作:输编号改单项 | ${c_bold}r${c_reset} 全部重来 | ${c_bold}回车${c_reset} 确认: ")" sel
|
|
|
+
|
|
|
+ if [[ -z "${sel}" ]]; then
|
|
|
+ break
|
|
|
+ elif [[ "${sel}" == "r" || "${sel}" == "R" ]]; then
|
|
|
+ for spec in "${specs[@]}"; do
|
|
|
+ IFS='|' read -r var prompt type default <<<"${spec}"
|
|
|
+ _ask_field "${var}" "${prompt}" "${type}" "${default}"
|
|
|
+ done
|
|
|
+ elif [[ "${sel}" =~ ^[0-9]+$ && "${sel}" -ge 1 && "${sel}" -le "${n}" ]]; then
|
|
|
+ IFS='|' read -r var prompt type default <<<"${specs[$((sel-1))]}"
|
|
|
+ _ask_field "${var}" "${prompt}" "${type}" "${default}"
|
|
|
+ else
|
|
|
+ warn "无效操作:${sel}"
|
|
|
+ fi
|
|
|
+ done
|
|
|
+}
|
|
|
+
|
|
|
+# 底层:逐字符读取密码,用 * 回显长度,支持退格,回车结束。
|
|
|
+# 用法:_read_secret_stars VAR "提示文案"
|
|
|
+_read_secret_stars() {
|
|
|
+ local __var="$1" __prompt="$2" __ch __acc=""
|
|
|
+ # 提示(不换行)
|
|
|
+ printf '%b' "${c_bold}${__prompt}${c_reset}: " > /dev/tty
|
|
|
+ # 逐字符读取(从 /dev/tty,避免受重定向影响)
|
|
|
+ while IFS= read -rsn1 __ch < /dev/tty; do
|
|
|
+ # 回车/换行结束
|
|
|
+ [[ -z "${__ch}" ]] && break
|
|
|
+ # 退格(DEL 0x7f 或 BS 0x08)
|
|
|
+ if [[ "${__ch}" == $'\x7f' || "${__ch}" == $'\x08' ]]; then
|
|
|
+ if [[ -n "${__acc}" ]]; then
|
|
|
+ __acc="${__acc%?}"
|
|
|
+ printf '\b \b' > /dev/tty
|
|
|
+ fi
|
|
|
+ continue
|
|
|
+ fi
|
|
|
+ __acc+="${__ch}"
|
|
|
+ printf '*' > /dev/tty
|
|
|
+ done
|
|
|
+ printf '\n' > /dev/tty
|
|
|
+ printf -v "${__var}" '%s' "${__acc}"
|
|
|
+}
|
|
|
+
|
|
|
+# 提示输入密码(* 回显 + 两次验证):ask_secret VAR "提示" "默认值"
|
|
|
+# 直接回车(空输入)则采用默认值(提示中明文显示),跳过二次确认;
|
|
|
+# 输入了内容则要求两次一致。
|
|
|
+ask_secret() {
|
|
|
+ local __var="$1" __prompt="$2" __default="${3:-}" __a __b
|
|
|
+ while :; do
|
|
|
+ _read_secret_stars __a "${__prompt}${__default:+ [回车用默认: ${__default}]}"
|
|
|
+ if [[ -z "${__a}" ]]; then
|
|
|
+ __a="${__default}"
|
|
|
+ break
|
|
|
+ fi
|
|
|
+ _read_secret_stars __b "${__prompt}(再输一次确认)"
|
|
|
+ [[ "${__a}" == "${__b}" ]] && break
|
|
|
+ warn "两次输入不一致,请重新输入。"
|
|
|
+ done
|
|
|
+ printf -v "${__var}" '%s' "${__a}"
|
|
|
+}
|
|
|
+
|
|
|
+# 强制输入密码(* 回显、无默认、必须非空且两次一致):ask_secret_required VAR "提示"
|
|
|
ask_secret_required() {
|
|
|
local __var="$1" __prompt="$2" __a __b
|
|
|
while :; do
|
|
|
- read -r -s -p "$(echo -e "${c_bold}${__prompt}${c_reset}: ")" __a; echo
|
|
|
+ _read_secret_stars __a "${__prompt}"
|
|
|
if [[ -z "${__a}" ]]; then
|
|
|
warn "不能为空,请重新输入。"; continue
|
|
|
fi
|
|
|
- read -r -s -p "$(echo -e "${c_bold}${__prompt}(再输一次确认)${c_reset}: ")" __b; echo
|
|
|
+ _read_secret_stars __b "${__prompt}(再输一次确认)"
|
|
|
if [[ "${__a}" != "${__b}" ]]; then
|
|
|
warn "两次输入不一致,请重新输入。"; continue
|
|
|
fi
|
|
|
@@ -149,6 +288,10 @@ KIRO_DO_LOGIN="n" # 安装后是否立即
|
|
|
GEN_CONFIG=""
|
|
|
GEN_MCP_CONFIG=""
|
|
|
|
|
|
+# 单项模式(--only):非空表示仅执行指定步骤,跳过步骤勾选交互
|
|
|
+ONLY_MODE=""
|
|
|
+ONLY_LABEL=""
|
|
|
+
|
|
|
# ---------------------------------------------------------------------------
|
|
|
# 步骤 0:选择模式与步骤
|
|
|
# ---------------------------------------------------------------------------
|
|
|
@@ -159,14 +302,19 @@ wizard_intro() {
|
|
|
echo "请选择部署目标:"
|
|
|
echo " 1) 本地部署 (local)"
|
|
|
echo " 2) 远程部署 (remote, 通过 SSH)"
|
|
|
- local sel; ask sel "输入序号" "1"
|
|
|
+ local sel; ask_choice sel "输入序号" "1" "1 2"
|
|
|
case "${sel}" in
|
|
|
1) MODE="local" ;;
|
|
|
2) MODE="remote" ;;
|
|
|
- *) err "无效选择"; exit 1 ;;
|
|
|
esac
|
|
|
ok "部署模式:${MODE}"
|
|
|
|
|
|
+ # --only 模式:步骤已由命令行参数设定,跳过交互勾选
|
|
|
+ if [[ -n "${ONLY_MODE}" ]]; then
|
|
|
+ echo "(单项模式:仅执行 ${ONLY_LABEL})"
|
|
|
+ return 0
|
|
|
+ fi
|
|
|
+
|
|
|
title "选择要执行的步骤"
|
|
|
ask_yn "① 检测/安装数据库引擎与依赖(PostgreSQL/Mongo/Redis/MinIO/Docker)?" "y" && DO_DEPS="y" || DO_DEPS="n"
|
|
|
ask_yn "② 安装 Casdoor(Docker,认证服务)?" "n" && DO_CASDOOR="y" || DO_CASDOOR="n"
|
|
|
@@ -190,19 +338,20 @@ wizard_intro() {
|
|
|
wizard_remote() {
|
|
|
[[ "${MODE}" == "remote" ]] || return 0
|
|
|
title "远程主机连接信息"
|
|
|
- ask R_HOST "远程主机地址 (IP 或域名)"
|
|
|
- [[ -n "${R_HOST}" ]] || { err "远程地址不能为空"; exit 1; }
|
|
|
- ask R_PORT "SSH 端口" "22"
|
|
|
- ask R_USER "SSH 登录用户" "${USER}"
|
|
|
- ask R_SSH_KEY "SSH 私钥路径(留空则用默认/密码)" ""
|
|
|
-
|
|
|
- info "测试 SSH 连接 ..."
|
|
|
- if ssh_run "echo connected" >/dev/null 2>&1; then
|
|
|
- ok "SSH 连接成功"
|
|
|
- else
|
|
|
+ while :; do
|
|
|
+ ask_required R_HOST "远程主机地址 (IP 或域名)"
|
|
|
+ ask R_PORT "SSH 端口" "22"
|
|
|
+ ask R_USER "SSH 登录用户" "${USER}"
|
|
|
+ ask R_SSH_KEY "SSH 私钥路径(留空则用默认/密码)" ""
|
|
|
+
|
|
|
+ info "测试 SSH 连接 ..."
|
|
|
+ if ssh_run "echo connected" >/dev/null 2>&1; then
|
|
|
+ ok "SSH 连接成功"
|
|
|
+ break
|
|
|
+ fi
|
|
|
err "SSH 连接失败,请检查地址/端口/用户/密钥"
|
|
|
- exit 1
|
|
|
- fi
|
|
|
+ ask_yn "重新填写连接信息并重试?" "y" || { warn "已取消"; exit 0; }
|
|
|
+ done
|
|
|
}
|
|
|
|
|
|
# 组装 ssh/scp 通用参数
|
|
|
@@ -240,84 +389,81 @@ run() {
|
|
|
# 步骤 2:部署参数与配置项
|
|
|
# ---------------------------------------------------------------------------
|
|
|
wizard_params() {
|
|
|
- title "部署目录与运行用户"
|
|
|
- ask DEPLOY_ROOT "部署根目录" "/var/www/fwh-toolbox"
|
|
|
- local def_user="${R_USER:-${USER}}"
|
|
|
- ask RUN_USER "后端 systemd 运行用户" "${def_user}"
|
|
|
+ edit_module "部署目录与运行用户" \
|
|
|
+ "DEPLOY_ROOT|部署根目录|plain|/var/www/fwh-toolbox" \
|
|
|
+ "RUN_USER|后端 systemd 运行用户|plain|${R_USER:-${USER}}"
|
|
|
|
|
|
if [[ "${DO_GENCONF}" == "y" ]]; then
|
|
|
- title "应用配置"
|
|
|
- ask APP_ENV "运行环境 (pro/dev)" "dev"
|
|
|
- ask APP_PORT "后端监听端口" "8301"
|
|
|
- ask ASYNQMON_PORT "Asynqmon 端口" "8302"
|
|
|
-
|
|
|
- title "PostgreSQL(本地)"
|
|
|
- ask PG_HOST "PG 主机" "localhost"
|
|
|
- ask PG_PORT "PG 端口" "5432"
|
|
|
- ask PG_DB "PG 数据库名" "fwh_toolbox_db"
|
|
|
- ask PG_USER "PG 业务角色" "fwh_toolbox"
|
|
|
- ask_secret PG_PASS "PG 业务角色密码" "fwh_toolbox"
|
|
|
-
|
|
|
- title "MongoDB / Redis"
|
|
|
- ask MONGO_DSN "Mongo 连接串" "mongodb://127.0.0.1:27017/FwhToolboxDb"
|
|
|
- ask REDIS_ADDR "Redis 地址" "localhost:6379"
|
|
|
-
|
|
|
- title "远端只读 MySQL(FWH 生产库,可留空跳过)"
|
|
|
- ask MYSQL_DSN "MySQL DSN" ""
|
|
|
-
|
|
|
- title "MinIO(本地对象存储)"
|
|
|
- ask MINIO_ENDPOINT "MinIO S3 API 地址" "localhost:9198"
|
|
|
- ask MINIO_ACCESS_KEY "MinIO Access Key" "fwh-toolbox"
|
|
|
- ask_secret MINIO_SECRET_KEY "MinIO Secret Key" "fwh-toolbox"
|
|
|
- ask MINIO_BUCKET "MinIO Bucket 名" "fwh-toolbox"
|
|
|
+ edit_module "应用配置" \
|
|
|
+ "APP_ENV|运行环境 (pro/dev)|plain|dev" \
|
|
|
+ "APP_PORT|后端监听端口|plain|8301" \
|
|
|
+ "ASYNQMON_PORT|Asynqmon 端口|plain|8302"
|
|
|
+
|
|
|
+ edit_module "PostgreSQL(本地)" \
|
|
|
+ "PG_HOST|PG 主机|plain|localhost" \
|
|
|
+ "PG_PORT|PG 端口|plain|5432" \
|
|
|
+ "PG_DB|PG 数据库名|plain|fwh_toolbox_db" \
|
|
|
+ "PG_USER|PG 业务角色|plain|fwh_toolbox" \
|
|
|
+ "PG_PASS|PG 业务角色密码|secret|fwh_toolbox"
|
|
|
+
|
|
|
+ edit_module "MongoDB / Redis" \
|
|
|
+ "MONGO_DSN|Mongo 连接串|plain|mongodb://127.0.0.1:27017/FwhToolboxDb" \
|
|
|
+ "REDIS_ADDR|Redis 地址|plain|localhost:6379"
|
|
|
+
|
|
|
+ edit_module "远端只读 MySQL(可留空跳过)" \
|
|
|
+ "MYSQL_DSN|MySQL DSN|optional|"
|
|
|
+
|
|
|
+ edit_module "MinIO(本地对象存储)" \
|
|
|
+ "MINIO_ENDPOINT|MinIO S3 API 地址|plain|localhost:9198" \
|
|
|
+ "MINIO_ACCESS_KEY|MinIO Access Key|plain|fwh-toolbox" \
|
|
|
+ "MINIO_SECRET_KEY|MinIO Secret Key|secret|fwh-toolbox" \
|
|
|
+ "MINIO_BUCKET|MinIO Bucket 名|plain|fwh-toolbox"
|
|
|
fi
|
|
|
|
|
|
if [[ "${DO_INITDB}" == "y" || "${DO_DEPS}" == "y" || "${DO_MINIOACCT}" == "y" ]]; then
|
|
|
- title "MinIO 管理员账户(安装/建桶/建账号用)"
|
|
|
- ask MINIO_ROOT_USER "MinIO 管理员用户" "jerry"
|
|
|
- ask_secret_required MINIO_ROOT_PASSWORD "MinIO 管理员密码(必填)"
|
|
|
+ edit_module "MinIO 管理员账户(安装/建桶/建账号用)" \
|
|
|
+ "MINIO_ROOT_USER|MinIO 管理员用户|plain|jerry" \
|
|
|
+ "MINIO_ROOT_PASSWORD|MinIO 管理员密码|secret_required|"
|
|
|
fi
|
|
|
|
|
|
if [[ "${DO_CASDOOR}" == "y" ]]; then
|
|
|
- title "Casdoor(Docker 认证服务)"
|
|
|
- local def_cdir="/home/${RUN_USER}/docker/casdoor"
|
|
|
- ask CASDOOR_DIR "Casdoor 部署目录" "${def_cdir}"
|
|
|
- ask CASDOOR_PORT "Casdoor 对外端口 (->容器8000)" "8010"
|
|
|
- ask CASDOOR_PG_USER "Casdoor 使用的 PG 角色" "casdoor"
|
|
|
- ask_secret CASDOOR_PG_PASSWORD "Casdoor PG 角色密码" "casdoor"
|
|
|
- ask CASDOOR_DB_NAME "Casdoor 数据库名" "casdoor"
|
|
|
+ edit_module "Casdoor(Docker 认证服务)" \
|
|
|
+ "CASDOOR_DIR|Casdoor 部署目录|plain|/home/${RUN_USER}/docker/casdoor" \
|
|
|
+ "CASDOOR_PORT|Casdoor 对外端口 (->容器8000)|plain|8010" \
|
|
|
+ "CASDOOR_PG_USER|Casdoor 使用的 PG 角色|plain|casdoor" \
|
|
|
+ "CASDOOR_PG_PASSWORD|Casdoor PG 角色密码|secret|casdoor" \
|
|
|
+ "CASDOOR_DB_NAME|Casdoor 数据库名|plain|casdoor"
|
|
|
+ # origin 默认值需引用上面刚填的 CASDOOR_PORT,故在 edit_module 之后单独询问
|
|
|
ask CASDOOR_ORIGIN "Casdoor 对外访问地址(origin)" "http://localhost:${CASDOOR_PORT}"
|
|
|
fi
|
|
|
|
|
|
if [[ "${DO_PGADMIN}" == "y" ]]; then
|
|
|
- title "pgAdmin4(数据库 Web 管理)"
|
|
|
- ask PGADMIN_PORT "pgAdmin4 对外端口" "5480"
|
|
|
- ask PGADMIN_BIND "pgAdmin4 绑定地址(默认仅本机,防公网暴露)" "127.0.0.1"
|
|
|
- ask PGADMIN_EMAIL "pgAdmin4 登录邮箱" "liang_jlyx@163.com"
|
|
|
- ask_secret_required PGADMIN_PASSWORD "pgAdmin4 登录密码(必填)"
|
|
|
- ask_secret_required POSTGRES_ADMIN_PASSWORD "postgres 超级用户新密码(供 pgAdmin 连接,必填)"
|
|
|
+ edit_module "pgAdmin4(数据库 Web 管理)" \
|
|
|
+ "PGADMIN_PORT|pgAdmin4 对外端口|plain|5480" \
|
|
|
+ "PGADMIN_BIND|pgAdmin4 绑定地址(默认仅本机,防公网暴露)|plain|127.0.0.1" \
|
|
|
+ "PGADMIN_EMAIL|pgAdmin4 登录邮箱|plain|liang_jlyx@163.com" \
|
|
|
+ "PGADMIN_PASSWORD|pgAdmin4 登录密码|secret_required|" \
|
|
|
+ "POSTGRES_ADMIN_PASSWORD|postgres 超级用户新密码(供 pgAdmin 连接)|secret_required|"
|
|
|
fi
|
|
|
|
|
|
if [[ "${DO_MINIOACCT}" == "y" ]]; then
|
|
|
- title "MinIO 业务账号(后端 fwh-toolbox / MCP fwh-toolbox-ai)"
|
|
|
- # 业务账号:默认 fwh-toolbox;若已在生成 config 时填过则复用,此处不重复询问
|
|
|
- [[ -n "${MINIO_ACCESS_KEY}" ]] || ask MINIO_ACCESS_KEY "后端业务 Access Key" "fwh-toolbox"
|
|
|
- [[ -n "${MINIO_SECRET_KEY}" ]] || ask_secret MINIO_SECRET_KEY "后端业务 Secret Key" "fwh-toolbox"
|
|
|
- # AI 账号(供 MCP 使用)
|
|
|
- ask MINIO_AI_ACCESS_KEY "AI Access Key(MCP 用)" "fwh-toolbox-ai"
|
|
|
- ask_secret MINIO_AI_SECRET_KEY "AI Secret Key(MCP 用,默认与账号一致)" "fwh-toolbox-ai"
|
|
|
- ask MINIO_AI_BUCKET "AI 文件 bucket 名" "fwh-toolbox-ai-file"
|
|
|
+ edit_module "MinIO 业务账号(后端 fwh-toolbox / MCP fwh-toolbox-ai)" \
|
|
|
+ "MINIO_ACCESS_KEY|后端业务 Access Key|plain|fwh-toolbox" \
|
|
|
+ "MINIO_SECRET_KEY|后端业务 Secret Key|secret|fwh-toolbox" \
|
|
|
+ "MINIO_AI_ACCESS_KEY|AI Access Key(MCP 用)|plain|fwh-toolbox-ai" \
|
|
|
+ "MINIO_AI_SECRET_KEY|AI Secret Key(MCP 用)|secret|fwh-toolbox-ai" \
|
|
|
+ "MINIO_AI_BUCKET|AI 文件 bucket 名|plain|fwh-toolbox-ai-file"
|
|
|
fi
|
|
|
|
|
|
if [[ "${DO_CADDY}" == "y" ]]; then
|
|
|
- title "Caddy 反向代理"
|
|
|
- ask CADDY_DOMAIN "对外域名 (如 lmt.zenpower.cc)"
|
|
|
- [[ -n "${CADDY_DOMAIN}" ]] || { err "Caddy 域名不能为空"; exit 1; }
|
|
|
- echo "TLS 走 spaceship DNS-01(自编译 caddy 内置该插件),请输入 spaceship API 凭据:"
|
|
|
- ask_secret_required LIBDNS_SPACESHIP_APIKEY "spaceship API Key(必填)"
|
|
|
- ask_secret_required LIBDNS_SPACESHIP_APISECRET "spaceship API Secret(必填)"
|
|
|
- ask CADDY_FRONTEND_PORT "前端静态端口" "8300"
|
|
|
- ask CADDY_BACKEND_PORT "后端 API 端口" "${APP_PORT}"
|
|
|
+ echo "TLS 走 spaceship DNS-01(自编译 caddy 内置该插件),需填 spaceship API 凭据。"
|
|
|
+ edit_module "Caddy 反向代理" \
|
|
|
+ "CADDY_DOMAIN|对外域名 (如 lmt.zenpower.cc)|required|" \
|
|
|
+ "LIBDNS_SPACESHIP_APIKEY|spaceship API Key|secret_required|" \
|
|
|
+ "LIBDNS_SPACESHIP_APISECRET|spaceship API Secret|secret_required|" \
|
|
|
+ "CADDY_FRONTEND_PORT|前端静态端口|plain|8300" \
|
|
|
+ "CADDY_BACKEND_PORT|后端 API 端口|plain|${APP_PORT}"
|
|
|
+ # 以下为 y/n 分支选项(即时询问,不纳入小结回改)
|
|
|
ask_yn "由 Caddy 直接 file_server 托管前端静态(否则反代到前端端口)?" "n" \
|
|
|
&& CADDY_SERVE_STATIC="y" || CADDY_SERVE_STATIC="n"
|
|
|
ask_yn "加入 /casdoor 反代?" "$( [[ ${DO_CASDOOR} == y ]] && echo y || echo n )" \
|
|
|
@@ -330,14 +476,13 @@ wizard_params() {
|
|
|
title "Kiro CLI(后端 AI 对话依赖)"
|
|
|
echo "将以运行用户 ${RUN_USER} 身份安装(其 HOME 决定 ~/.kiro 配置位置)。"
|
|
|
echo "安装方式:1) zip 官方安装包(默认) 2) curl 一键脚本"
|
|
|
- local _km; ask _km "输入序号" "1"
|
|
|
+ local _km; ask_choice _km "输入序号" "1" "1 2"
|
|
|
case "${_km}" in
|
|
|
1) KIRO_INSTALL_METHOD="zip"
|
|
|
echo "C 库变体:1) gnu(默认,主流发行版) 2) musl(Alpine 等)"
|
|
|
- local _kl; ask _kl "输入序号" "1"
|
|
|
+ local _kl; ask_choice _kl "输入序号" "1" "1 2"
|
|
|
[[ "${_kl}" == "2" ]] && KIRO_LIBC="musl" || KIRO_LIBC="gnu" ;;
|
|
|
2) KIRO_INSTALL_METHOD="curl" ;;
|
|
|
- *) err "无效选择"; exit 1 ;;
|
|
|
esac
|
|
|
ask_yn "安装后立即以 ${RUN_USER} 身份登录 Builder ID(交互式,需浏览器)?" "n" \
|
|
|
&& KIRO_DO_LOGIN="y" || KIRO_DO_LOGIN="n"
|
|
|
@@ -812,6 +957,9 @@ FranklinWH Toolbox 交互式一键部署
|
|
|
|
|
|
用法:
|
|
|
$0 进入交互式向导(选择 local/remote,分步选择与填写)
|
|
|
+ $0 --only <项[,项...]> 只执行指定步骤(仍会先问 local/remote 与该步骤参数)
|
|
|
+ 可选项:deps casdoor initdb minioacct pgadmin caddy kiro deploy
|
|
|
+ 例:$0 --only caddy 或 $0 --only deps,initdb
|
|
|
$0 --help 显示本帮助
|
|
|
|
|
|
向导步骤:
|
|
|
@@ -831,9 +979,54 @@ FranklinWH Toolbox 交互式一键部署
|
|
|
EOF
|
|
|
}
|
|
|
|
|
|
+# --only 解析:把所有步骤关掉,再按传入项打开对应步骤
|
|
|
+# 支持项:deps casdoor initdb minioacct pgadmin caddy kiro deploy
|
|
|
+# 多项用逗号分隔,如 --only deps,initdb
|
|
|
+parse_only() {
|
|
|
+ local items="$1"
|
|
|
+ [[ -n "${items}" ]] || { err "--only 需要指定步骤,如:--only caddy(可选 deps,casdoor,initdb,minioacct,pgadmin,caddy,kiro,deploy)"; exit 1; }
|
|
|
+
|
|
|
+ # 全部关闭
|
|
|
+ DO_DEPS="n"; DO_CASDOOR="n"; DO_INITDB="n"; DO_BACKEND="n"; DO_FRONTEND="n"
|
|
|
+ DO_GENCONF="n"; DO_CADDY="n"; DO_KIRO="n"; DO_PGADMIN="n"; DO_MINIOACCT="n"
|
|
|
+
|
|
|
+ ONLY_MODE=1
|
|
|
+ ONLY_LABEL="${items}"
|
|
|
+
|
|
|
+ local IFS=','; local it
|
|
|
+ for it in ${items}; do
|
|
|
+ case "${it}" in
|
|
|
+ deps) DO_DEPS="y" ;;
|
|
|
+ casdoor) DO_CASDOOR="y" ;;
|
|
|
+ initdb) DO_INITDB="y"; DO_GENCONF="y" ;; # 初始化通常配合生成 config
|
|
|
+ minioacct) DO_MINIOACCT="y" ;;
|
|
|
+ pgadmin) DO_PGADMIN="y" ;;
|
|
|
+ caddy) DO_CADDY="y" ;;
|
|
|
+ kiro) DO_KIRO="y" ;;
|
|
|
+ deploy)
|
|
|
+ # 部署前后端:子交互选择范围
|
|
|
+ echo "部署范围:1) 前端+后端(all) 2) 仅后端 3) 仅前端"
|
|
|
+ local _sel; ask_choice _sel "输入序号" "1" "1 2 3"
|
|
|
+ case "${_sel}" in
|
|
|
+ 1) DO_BACKEND="y"; DO_FRONTEND="y" ;;
|
|
|
+ 2) DO_BACKEND="y"; DO_FRONTEND="n" ;;
|
|
|
+ 3) DO_BACKEND="n"; DO_FRONTEND="y" ;;
|
|
|
+ esac
|
|
|
+ DO_GENCONF="y" # 部署后端需要 config.env
|
|
|
+ ;;
|
|
|
+ *) err "未知 --only 项:${it}"; exit 1 ;;
|
|
|
+ esac
|
|
|
+ done
|
|
|
+}
|
|
|
+
|
|
|
main() {
|
|
|
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then usage; exit 0; fi
|
|
|
|
|
|
+ # --only <项[,项...]>:单项/多项模式,仅执行指定步骤
|
|
|
+ if [[ "${1:-}" == "--only" ]]; then
|
|
|
+ parse_only "${2:-}"
|
|
|
+ fi
|
|
|
+
|
|
|
trap cleanup EXIT
|
|
|
|
|
|
wizard_intro
|