From 679b0d31d3ed13a5bcacc33d97b3de33c290ddec Mon Sep 17 00:00:00 2001 From: admin Date: Wed, 2 Sep 2026 07:40:30 +0000 Subject: [PATCH] release: sync public installer asset install.sh --- install.sh | 67 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/install.sh b/install.sh index 3741b4b..f54c50a 100644 --- a/install.sh +++ b/install.sh @@ -33,6 +33,8 @@ if [[ -n ${XYMEDIA_INSTALL_TEST_TTY:-} ]]; then TTY_TEST_MODE=1; mapfile -t TTY_ XIAOYA_DIR=${XYMEDIA_XIAOYA_DIR:-} XIAOYA_CONTAINER_EXPLICIT=${XYMEDIA_XIAOYA_CONTAINER:+1} XIAOYA_CONTAINER=${XYMEDIA_XIAOYA_CONTAINER:-xymedia-xiaoya} +OPTION2_XIAOYA_PENDING=0 +XIAOYA_FOUND=0 CONTROLLER_ONLY=0 MENU_PROFILES= CONTROLLER_URL=${XYMEDIA_XIAOYA_CONTROLLER_URL:-} @@ -373,7 +375,7 @@ menu() { read_tty choice || die '无法读取终端输入' case "$choice" in 1) return 0;; - 2) ensure_xiaoya_dir; printf '小雅目录已准备:%s;将安装小雅和小雅控制器。\n' "$XIAOYA_DIR" >>$TTY_OUT; write_controller_token; CONTROLLER_URL='http://xymedia-controller:19090'; [[ -f "$INSTALL_DIR/.env" ]] || XYMEDIA_XIAOYA_MANAGED=1; MENU_PROFILES='xiaoya xiaoya-control'; return 0;; + 2) ensure_xiaoya_dir; printf '小雅目录已准备:%s;安装器将在 Docker 检查后检测并复用已有小雅。\n' "$XIAOYA_DIR" >>$TTY_OUT; write_controller_token; CONTROLLER_URL='http://xymedia-controller:19090'; OPTION2_XIAOYA_PENDING=1; return 0;; 3) local url name key; url=$(prompt_tty '控制器地址:'); key=$(prompt_tty '控制器密钥:'); name=$(prompt_tty '显示名称:'); [[ $url == https://* || ${ALLOW_HTTP:-0} == 1 ]] || die '远程连接默认要求 HTTPS;设置 ALLOW_HTTP=1 后才允许 HTTP'; curl --fail --silent --show-error --location --max-time 10 -H "X-XyMedia-Controller-Token: $key" "${url%/}/health" >/dev/null || die '控制器健康检查失败,未保存连接'; REMOTE_MODE=1; REMOTE_TOKEN=$key; CONTROLLER_URL="${url%/}"; printf '远程连接 %s (%s) 校验成功,配置已保存;控制器密钥不会显示。\n' "$name" "$CONTROLLER_URL" >>$TTY_OUT; return 0;; 4) ensure_xiaoya_dir 1; if [[ ${XYMEDIA_INSTALL_TEST_DISCOVERY_ONLY:-0} != 1 && -z $CONTROLLER_BIND_EXPLICIT ]]; then prompt_tty_into CONTROLLER_BIND_ADDRESS "控制器监听地址 [${CONTROLLER_BIND_ADDRESS}]: "; CONTROLLER_BIND_ADDRESS=${CONTROLLER_BIND_ADDRESS:-0.0.0.0}; fi; if [[ ${XYMEDIA_INSTALL_TEST_DISCOVERY_ONLY:-0} != 1 && -z $CONTROLLER_PORT_EXPLICIT ]]; then prompt_tty_into CONTROLLER_PORT "控制器端口 [${CONTROLLER_PORT}]: "; CONTROLLER_PORT=${CONTROLLER_PORT:-19090}; fi; write_controller_token; CONTROLLER_ONLY=1; printf '小雅控制器安装目录已准备。\n' >>$TTY_OUT; MENU_PROFILES='xiaoya-control'; return 0;; 5) while :; do @@ -394,11 +396,17 @@ menu() { esac done } -menu "$@" -if [[ ${XYMEDIA_INSTALL_TEST_MENU_ONLY:-0} == 1 ]]; then - printf 'TEST_MENU_PROFILES=%s\n' "$MENU_PROFILES" >$TTY_OUT - exit 0 +if [[ -f "$INSTALL_DIR/.env" ]]; then + [[ -n ${XYMEDIA_XIAOYA_DIR:-} ]] || XIAOYA_DIR=$(read_install_env XYMEDIA_XIAOYA_DATA_DIR) + if [[ -z ${XYMEDIA_XIAOYA_CONTAINER:-} ]]; then + existing_xiaoya_container=$(read_install_env XYMEDIA_XIAOYA_CONTAINER) + if [[ -n $existing_xiaoya_container ]]; then + XIAOYA_CONTAINER=$existing_xiaoya_container + XIAOYA_CONTAINER_EXPLICIT=1 + fi + fi fi +menu "$@" validate_controller_settings() { [[ $CONTROLLER_PORT =~ ^[0-9]+$ && $CONTROLLER_PORT -ge 1 && $CONTROLLER_PORT -le 65535 ]] || die '控制器端口必须是 1 到 65535 之间的数字' [[ $CONTROLLER_BIND_ADDRESS != *$'\r'* && $CONTROLLER_BIND_ADDRESS != *$'\n'* ]] || die '控制器监听地址不能包含换行' @@ -423,6 +431,18 @@ progress '检查安装环境' [[ $INSTALL_DIR = /* && $INSTALL_DIR != / ]] || die '安装目录必须是绝对路径且不能是根目录' guard_existing_install_tree if [[ -f "$INSTALL_DIR/.env" ]]; then INSTALL_EXISTING=1; fi +if (( INSTALL_EXISTING )); then + if [[ -z ${XYMEDIA_XIAOYA_DIR:-} ]]; then + XIAOYA_DIR=$(read_install_env XYMEDIA_XIAOYA_DATA_DIR) + fi + if [[ -z ${XYMEDIA_XIAOYA_CONTAINER:-} ]]; then + existing_xiaoya_container=$(read_install_env XYMEDIA_XIAOYA_CONTAINER) + if [[ -n $existing_xiaoya_container ]]; then + XIAOYA_CONTAINER=$existing_xiaoya_container + XIAOYA_CONTAINER_EXPLICIT=1 + fi + fi +fi init_installer_log command -v docker >/dev/null || die '需要安装 Docker' if docker compose version >/dev/null 2>&1; then COMPOSE=(docker compose); elif command -v docker-compose >/dev/null; then COMPOSE=(docker-compose); else die '需要安装 Docker Compose'; fi @@ -464,6 +484,7 @@ discover_xiaoya_container() { local -a ids=() candidates=() ordered=() if [[ -n ${XIAOYA_CONTAINER_EXPLICIT:-} ]]; then docker container inspect "$XIAOYA_CONTAINER" >/dev/null 2>&1 || die "未找到小雅容器:$XIAOYA_CONTAINER" + XIAOYA_FOUND=1 printf '使用指定的小雅容器:%s(Docker inspect 已确认)\n' "$XIAOYA_CONTAINER" >>$TTY_OUT return 0 fi @@ -489,14 +510,21 @@ except (ValueError, IndexError, TypeError, AttributeError): for record in "${candidates[@]}"; do [[ $record == *$'\trunning' ]] && ordered+=("$record"); done for record in "${candidates[@]}"; do [[ $record == *$'\trunning' ]] || ordered+=("$record"); done if ((${#ordered[@]} == 0)); then + if (( OPTION2_XIAOYA_PENDING )); then + XIAOYA_FOUND=0 + XIAOYA_CONTAINER=xymedia-xiaoya + return 0 + fi prompt_tty_into selected '未自动发现小雅容器,请输入容器名称(将执行 Docker inspect):' [[ -n $selected ]] || die '小雅容器名称不能为空' docker container inspect "$selected" >/dev/null 2>&1 || die "容器不存在或无法 inspect:$selected" XIAOYA_CONTAINER=$selected + XIAOYA_FOUND=1 printf '已确认手动指定的小雅容器:%s\n' "$XIAOYA_CONTAINER" >>$TTY_OUT elif ((${#ordered[@]} == 1)); then IFS=$'\t' read -r XIAOYA_CONTAINER image state <<<"${ordered[0]}" printf '自动发现小雅容器:%s(镜像:%s,状态:%s)\n' "$XIAOYA_CONTAINER" "$image" "$state" >>$TTY_OUT + XIAOYA_FOUND=1 [[ $state == running ]] || printf '警告:小雅容器当前已停止;仍允许安装控制器,状态页会提示。\n' >>$TTY_OUT else printf '发现多个可能的小雅容器(运行中的优先):\n' >>$TTY_OUT @@ -509,10 +537,26 @@ except (ValueError, IndexError, TypeError, AttributeError): prompt_tty_into choice '请选择容器编号:' [[ $choice =~ ^[0-9]+$ && $choice -ge 1 && $choice -le ${#ordered[@]} ]] || die '无效的小雅容器编号' IFS=$'\t' read -r XIAOYA_CONTAINER image state <<<"${ordered[$((choice - 1))]}" + XIAOYA_FOUND=1 printf '已选择小雅容器:%s(镜像:%s,状态:%s)\n' "$XIAOYA_CONTAINER" "$image" "$state" >>$TTY_OUT [[ $state == running ]] || printf '警告:小雅容器当前已停止;仍允许安装控制器,状态页会提示。\n' >>$TTY_OUT fi } +prepare_option2_xiaoya() { + (( OPTION2_XIAOYA_PENDING )) || return 0 + discover_xiaoya_container + validate_container_name + if (( XIAOYA_FOUND )); then + validate_xiaoya_data_dir + XYMEDIA_XIAOYA_MANAGED=0 + MENU_PROFILES='xiaoya-control' + printf '检测到已有小雅容器:%s,将复用,不创建新的小雅容器。\n' "$XIAOYA_CONTAINER" >>$TTY_OUT + else + XYMEDIA_XIAOYA_MANAGED=1 + MENU_PROFILES='xiaoya xiaoya-control' + printf '未检测到已有小雅容器,将安装新的小雅容器:%s。\n' "$XIAOYA_CONTAINER" >>$TTY_OUT + fi +} validate_xiaoya_data_dir() { local inspect_json [[ -d $XIAOYA_DIR && $XIAOYA_DIR = /* && $XIAOYA_DIR != / ]] || die '小雅数据目录必须是已存在的绝对目录' @@ -585,6 +629,11 @@ if (( CONTROLLER_ONLY )); then [[ ${XYMEDIA_INSTALL_TEST_DISCOVERY_ONLY:-0} == 1 ]] && exit 0 validate_xiaoya_data_dir fi +prepare_option2_xiaoya +if [[ ${XYMEDIA_INSTALL_TEST_MENU_ONLY:-0} == 1 || ${XYMEDIA_INSTALL_TEST_OPTION2_ONLY:-0} == 1 ]]; then + printf 'TEST_MENU_PROFILES=%s\nTEST_XIAOYA_CONTAINER=%s\nTEST_XIAOYA_MANAGED=%s\n' "$MENU_PROFILES" "$XIAOYA_CONTAINER" "${XYMEDIA_XIAOYA_MANAGED:-0}" >>$TTY_OUT + exit 0 +fi if (( ! CONTROLLER_ONLY )) && (( PG_HOST_CLI )) && [[ $PG_HOST != postgres && $EXISTING_DB != 1 ]]; then die 'an external database requires --existing-db confirmation'; fi if (( ! CONTROLLER_ONLY )) && (( PG_HOST_CLI )) && [[ $PG_HOST != postgres && -z $PG_PASSWORD_FILE ]]; then die 'an external database requires --postgres-password-file'; fi if ! [[ $API_PORT =~ ^[0-9]+$ && $WEBDAV_PORT =~ ^[0-9]+$ && $TVBOX_PORT =~ ^[0-9]+$ ]]; then die 'ports must be numeric'; fi @@ -980,7 +1029,9 @@ tmp.write_text(text) tmp.replace(p) PY if [[ -n $MENU_PROFILES ]]; then - [[ ${XYMEDIA_INSTALL_CONFIRM:-} == INSTALL_XIAOYA ]] || { confirm=$(prompt_tty '安装小雅将创建并启动相关容器,输入 1 继续,其他内容取消: '); [[ $confirm == 1 ]] || die '已取消小雅安装'; } + if [[ ${XYMEDIA_XIAOYA_MANAGED:-0} == 1 ]]; then + [[ ${XYMEDIA_INSTALL_CONFIRM:-} == INSTALL_XIAOYA ]] || { confirm=$(prompt_tty '安装小雅将创建并启动相关容器,输入 1 继续,其他内容取消: '); [[ $confirm == 1 ]] || die '已取消小雅安装'; } + fi for profile in $MENU_PROFILES; do run_logged "${COMPOSE[@]}" --profile "$profile" --project-directory "$INSTALL_DIR" --env-file "$INSTALL_DIR/.env" -f "$INSTALL_DIR/compose.yaml" up -d || die "小雅 profile 启动失败:$profile"; done if [[ $MENU_PROFILES == *xiaoya-control* ]]; then controller_state=$(docker inspect --format '{{.State.Status}}' xymedia-controller 2>>"$INSTALL_LOG" || true) @@ -1075,7 +1126,7 @@ if [[ $migration_rc -ne 0 ]]; then fi printf '数据库初始化完成\n' printf '数据库初始化完成\n' >>"$INSTALL_LOG" -if [[ $MENU_PROFILES == 'xiaoya xiaoya-control' ]]; then +if [[ $MENU_PROFILES == *xiaoya-control* ]]; then printf '本机小雅控制器连接信息:\n' print_controller_info fi @@ -1119,7 +1170,7 @@ wait_for_app_health || die 'XyMediaVault 健康检查被中断,安装未完成 cp "$INSTALL_LOG" "$INSTALL_DIR/install.log" 2>/dev/null || true printf '\033[2K\r[%d/%d] 安装完成:XyMediaVault 已就绪\n' "$TOTAL_STEPS" "$TOTAL_STEPS" printf '管理地址:http://127.0.0.1:%s\n' "$API_PORT" - if [[ $MENU_PROFILES == 'xiaoya xiaoya-control' ]]; then + if [[ $MENU_PROFILES == *xiaoya-control* ]]; then print_controller_info fi if (( LOCAL_DB )); then