From 8f6402aeb021da9f3dc197bad9f2fb2e4c0c8a1e Mon Sep 17 00:00:00 2001 From: admin Date: Wed, 9 Sep 2026 02:47:04 +0000 Subject: [PATCH] release: sync public installer asset install.sh --- install.sh | 50 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/install.sh b/install.sh index bf54f09..1b9145a 100644 --- a/install.sh +++ b/install.sh @@ -33,6 +33,26 @@ TTY_TEST_MODE=0 TTY_TEST_INDEX=0 TTY_TEST_LINES=() if [[ -n ${XYMEDIA_INSTALL_TEST_TTY:-} ]]; then TTY_TEST_MODE=1; mapfile -t TTY_TEST_LINES <"$TTY_IN"; fi +TERMINAL_CAPABLE=0 +COLOR_ENABLED=0 +TERMINAL_REDRAW=0 +COLOR_RESET= COLOR_TITLE= COLOR_RECOMMENDED= COLOR_HINT= COLOR_SECTION= COLOR_WARNING= +ERROR_COLOR= ERROR_RESET= +if [[ -r $TTY_IN && -w $TTY_OUT && -c $TTY_OUT ]]; then + TERMINAL_CAPABLE=1 +fi +if (( TERMINAL_CAPABLE && ! TTY_TEST_MODE )) && [[ -z ${NO_COLOR+x} && ${TERM:-} != dumb ]]; then + COLOR_ENABLED=1 + TERMINAL_REDRAW=1 + COLOR_RESET=$'\033[0m' + COLOR_TITLE=$'\033[1;36m' + COLOR_RECOMMENDED=$'\033[1;32m' + COLOR_HINT=$'\033[2;37m' + COLOR_SECTION=$'\033[1;34m' + COLOR_WARNING=$'\033[1;31m' + ERROR_COLOR=$'\033[31m' + ERROR_RESET=$'\033[0m' +fi XIAOYA_DIR=${XYMEDIA_XIAOYA_DIR:-} XIAOYA_CONTAINER_EXPLICIT=${XYMEDIA_XIAOYA_CONTAINER:+1} XIAOYA_CONTAINER=${XYMEDIA_XIAOYA_CONTAINER:-xymedia-xiaoya} @@ -301,7 +321,7 @@ persist_installer_log() { cp "$INSTALL_LOG" "$INSTALL_DIR/install.log" 2>/dev/null || true chmod 600 "$INSTALL_DIR/install.log" 2>/dev/null || true } -die() { printf '\n\033[31mxymediavault installer: %s\033[0m\n' "$*" >&2; persist_installer_log; [[ -f ${INSTALL_DIR:-}/install.log ]] && printf '详情日志:%s/install.log\n' "$INSTALL_DIR" >&2 || { [[ -n $INSTALL_LOG ]] && printf '详情日志:%s\n' "$INSTALL_LOG" >&2; }; exit 1; } +die() { printf '\n%sxymediavault installer: %s%s\n' "$ERROR_COLOR" "$*" "$ERROR_RESET" >&2; persist_installer_log; [[ -f ${INSTALL_DIR:-}/install.log ]] && printf '详情日志:%s/install.log\n' "$INSTALL_DIR" >&2 || { [[ -n $INSTALL_LOG ]] && printf '详情日志:%s\n' "$INSTALL_LOG" >&2; }; exit 1; } component_cache_test_mode() { local catalog=${XYMEDIA_INSTALL_TEST_CATALOG:?} component platform version url sha archive marker_version marker_sha stage downloaded tarball actual mkdir -p "$INSTALL_DIR/components" "$INSTALL_DIR/state" @@ -413,11 +433,19 @@ ensure_instance_id() { } progress() { STEP=$((STEP + 1)) - printf '\033[2K\r[%d/%d] %s\n' "$STEP" "$TOTAL_STEPS" "$1" + terminal_status "[$STEP/$TOTAL_STEPS] $1" 1 if [[ -n $INSTALL_LOG ]]; then printf '[%d/%d] %s\n' "$STEP" "$TOTAL_STEPS" "$1" >>"$INSTALL_LOG" fi } +terminal_status() { + if (( TERMINAL_REDRAW )); then + printf '\033[2K\r%s' "$1" + [[ ${2:-0} == 1 ]] && printf '\n' + else + printf '%s\n' "$1" + fi +} run_logged() { if "$@" >>"$INSTALL_LOG" 2>&1; then return 0 @@ -571,7 +599,7 @@ menu() { [[ $# -eq 0 ]] || return 0 [[ -r $TTY_IN && -w $TTY_OUT ]] || die '没有可用终端:安装菜单不能通过非交互管道运行' while :; do - printf '\nXyMediaVault 安装器\n1) 推荐安装:管理平台和本机小雅(新用户、单机部署、默认推荐)\n2) 仅安装管理平台(只需要平台,暂不接入小雅)\n3) 安装管理平台并连接远程小雅控制器(小雅在另一台机器)\n4) 仅安装小雅控制器(这台机器只负责运行小雅控制器)\n5) 状态/诊断/维护\n6) 查看小雅控制器地址和密钥\n7) 查看数据库连接信息\n0) 退出\n提示:首次本机部署请选择 1;已有本机 Alist/小雅可在 1 中选择复用或独立安装。\n选择:' >>$TTY_OUT + printf '\n%sXyMediaVault 安装器%s\n%s----------------------------------------%s\n%s1) 推荐安装:管理平台和本机小雅(新用户、单机部署、默认推荐)%s\n2) 仅安装管理平台(只需要平台,暂不接入小雅)\n3) 安装管理平台并连接远程小雅控制器(小雅在另一台机器)\n4) 仅安装小雅控制器(这台机器只负责运行小雅控制器)\n%s----------------------------------------%s\n%s5) 状态/诊断/维护%s\n6) 查看小雅控制器地址和密钥\n7) 查看数据库连接信息\n0) 退出\n%s提示:首次本机部署请选择 1;已有本机 Alist/小雅可在 1 中选择复用或独立安装。%s\n选择:' "$COLOR_TITLE" "$COLOR_RESET" "$COLOR_SECTION" "$COLOR_RESET" "$COLOR_RECOMMENDED" "$COLOR_RESET" "$COLOR_SECTION" "$COLOR_RESET" "$COLOR_SECTION" "$COLOR_RESET" "$COLOR_HINT" "$COLOR_RESET" >>$TTY_OUT read_tty choice || die '无法读取终端输入' case "$choice" in 1) write_controller_token; CONTROLLER_URL='http://xymedia-controller:19090'; OPTION2_XIAOYA_PENDING=1; return 0;; @@ -579,14 +607,14 @@ menu() { 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 - printf '\n维护菜单\n1) 查看状态\n2) 一键挂载本地媒体库\n3) 启动/重启已配置挂载\n4) 停用本地媒体库挂载\n5) 清理 XyMediaVault 容器及数据\n0) 返回\n选择:' >>$TTY_OUT + printf '\n%s维护菜单%s\n%s----------------------------------------%s\n1) 查看状态\n2) 一键挂载本地媒体库\n3) 启动/重启已配置挂载\n4) 停用本地媒体库挂载\n%s[!] 清理 XyMediaVault 容器及数据%s\n%s----------------------------------------%s\n0) 返回\n选择:' "$COLOR_SECTION" "$COLOR_RESET" "$COLOR_SECTION" "$COLOR_RESET" "$COLOR_WARNING" "$COLOR_RESET" "$COLOR_SECTION" "$COLOR_RESET" >>$TTY_OUT read_tty maintenance_choice || die '无法读取终端输入' case "$maintenance_choice" in 1) require_public_app_installation || continue; print_fuse_status;; 2) require_public_app_installation || continue; prompt_tty_into FUSE_PATH_INPUT '宿主机媒体库目录(必须为空):'; confirm_fuse_action; MAINTENANCE_ACTION=configure; return 0;; 3) require_public_app_installation || continue; confirm_fuse_action; MAINTENANCE_ACTION=restart; return 0;; 4) require_public_app_installation || continue; confirm_fuse_action; MAINTENANCE_ACTION=disable; return 0;; - 5) printf '清理选项:\n1) 只清理 XyMediaVault\n2) 清理 XyMediaVault 和本机安装的小雅\n0) 取消\n选择:' >>$TTY_OUT; read_tty cleanup_choice || die '无法读取终端输入'; case "$cleanup_choice" in 1) CLEANUP_CHOICE=1; return 0;; 2) CLEANUP_CHOICE=2; return 0;; 0) continue;; *) printf '无效选择\n' >>$TTY_OUT;; esac;; + 5) printf '%s清理选项:%s\n%s----------------------------------------%s\n%s1) 只清理 XyMediaVault%s\n%s2) 清理 XyMediaVault 和本机安装的小雅%s\n0) 取消\n选择:' "$COLOR_WARNING" "$COLOR_RESET" "$COLOR_SECTION" "$COLOR_RESET" "$COLOR_WARNING" "$COLOR_RESET" "$COLOR_WARNING" "$COLOR_RESET" >>$TTY_OUT; read_tty cleanup_choice || die '无法读取终端输入'; case "$cleanup_choice" in 1) CLEANUP_CHOICE=1; return 0;; 2) CLEANUP_CHOICE=2; return 0;; 0) continue;; *) printf '无效选择\n' >>$TTY_OUT;; esac;; 0) continue 2;; *) printf '无效选择\n' >>$TTY_OUT;; esac done;; @@ -1483,12 +1511,12 @@ if (( LOCAL_DB )); then health=$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "$container_id" 2>>"$INSTALL_LOG" || true) fi if [[ $health == healthy ]]; then - printf '\033[2K\r[%d/%d] PostgreSQL 已就绪(%s 秒)\n' "$STEP" "$TOTAL_STEPS" "$elapsed" + terminal_status "[$STEP/$TOTAL_STEPS] PostgreSQL 已就绪($elapsed 秒)" 1 [[ -n $previous_int ]] && eval "$previous_int" || trap - INT [[ -n $previous_term ]] && eval "$previous_term" || trap - TERM return 0 fi - printf '\033[2K\r[%d/%d] 等待 PostgreSQL 就绪(已用 %s 秒,状态:%s)' "$STEP" "$TOTAL_STEPS" "$elapsed" "${health:-unknown}" + terminal_status "[$STEP/$TOTAL_STEPS] 等待 PostgreSQL 就绪(已用 $elapsed 秒,状态:${health:-unknown})" printf 'PostgreSQL status: elapsed=%s health=%s\n' "$elapsed" "${health:-unknown}" >>"$INSTALL_LOG" sleep 2 done @@ -1517,11 +1545,11 @@ wait_postgres_external() { client_command=(docker run --rm --network "$db_network" -e "PGPASSWORD=$PG_PASSWORD" postgres:17-bookworm psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$PG_DB" -c 'SELECT 1') if "${client_command[@]}" >>"$INSTALL_LOG" 2>&1; then elapsed=$(( $(date +%s) - started_at )) - printf '\033[2K\r[%d/%d] PostgreSQL 外部连接已验证(%s 秒)\n' "$STEP" "$TOTAL_STEPS" "$elapsed" + terminal_status "[$STEP/$TOTAL_STEPS] PostgreSQL 外部连接已验证($elapsed 秒)" 1 return 0 fi elapsed=$(( $(date +%s) - started_at )) - printf '\033[2K\r[%d/%d] 数据库外部连接仍在等待(%s秒)' "$STEP" "$TOTAL_STEPS" "$elapsed" + terminal_status "[$STEP/$TOTAL_STEPS] 数据库外部连接仍在等待(${elapsed}秒)" printf 'PostgreSQL external status: elapsed=%s host=%s port=%s\n' "$elapsed" "$PG_HOST" "$PG_PORT" >>"$INSTALL_LOG" sleep 2 done @@ -1618,7 +1646,7 @@ wait_for_app_health() { [[ -n $previous_term ]] && eval "$previous_term" || trap - TERM return 0 fi - printf '\033[2K\r[%d/%d] 等待 XyMediaVault 健康检查(已用 %s 秒)' "$STEP" "$TOTAL_STEPS" "$elapsed" + terminal_status "[$STEP/$TOTAL_STEPS] 等待 XyMediaVault 健康检查(已用 $elapsed 秒)" printf 'XyMediaVault health status: elapsed=%s\n' "$elapsed" >>"$INSTALL_LOG" sleep 2 done @@ -1632,7 +1660,7 @@ else fi if (( RELEASE_ROLLBACK_ACTIVE )); then rm -rf -- "$release_backup"; RELEASE_ROLLBACK_ACTIVE=0; fi cp "$INSTALL_LOG" "$INSTALL_DIR/install.log" 2>/dev/null || true - printf '\033[2K\r[%d/%d] 安装完成:XyMediaVault 已就绪\n' "$TOTAL_STEPS" "$TOTAL_STEPS" + terminal_status "[$TOTAL_STEPS/$TOTAL_STEPS] 安装完成:XyMediaVault 已就绪" 1 management_address=$(printf '%s\n' "$HOST_ADDRESSES_INITIAL" | head -n 1) [[ -n $management_address ]] || management_address=127.0.0.1 if [[ $management_address == *:* ]]; then management_address="[$management_address]"; fi