mirror of
				https://gitee.com/SuperManito/LinuxMirrors
				synced 2025-11-04 08:20:28 +08:00 
			
		
		
		
	代码结构优化
This commit is contained in:
		
							
								
								
									
										437
									
								
								ChangeMirrors.sh
									
									
									
									
									
								
							
							
						
						
									
										437
									
								
								ChangeMirrors.sh
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,12 +1,12 @@
 | 
				
			|||||||
#!/bin/bash
 | 
					#!/bin/bash
 | 
				
			||||||
## Author: SuperManito
 | 
					## Author: SuperManito
 | 
				
			||||||
## Modified: 2025-07-04
 | 
					## Modified: 2025-07-18
 | 
				
			||||||
## License: MIT
 | 
					## License: MIT
 | 
				
			||||||
## GitHub: https://github.com/SuperManito/LinuxMirrors
 | 
					## GitHub: https://github.com/SuperManito/LinuxMirrors
 | 
				
			||||||
## Website: https://linuxmirrors.cn
 | 
					## Website: https://linuxmirrors.cn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Docker CE 软件源列表
 | 
					## Docker CE 软件源列表
 | 
				
			||||||
# 格式:"软件源名称@软件源地址"
 | 
					# 格式:"名称@地址"
 | 
				
			||||||
mirror_list_docker_ce=(
 | 
					mirror_list_docker_ce=(
 | 
				
			||||||
    "阿里云@mirrors.aliyun.com/docker-ce"
 | 
					    "阿里云@mirrors.aliyun.com/docker-ce"
 | 
				
			||||||
    "腾讯云@mirrors.tencent.com/docker-ce"
 | 
					    "腾讯云@mirrors.tencent.com/docker-ce"
 | 
				
			||||||
@@ -24,7 +24,7 @@ mirror_list_docker_ce=(
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Docker Registry 仓库列表
 | 
					## Docker Registry 仓库列表
 | 
				
			||||||
# 格式:"软件源名称@软件源地址"
 | 
					# 格式:"名称@地址"
 | 
				
			||||||
mirror_list_registry=(
 | 
					mirror_list_registry=(
 | 
				
			||||||
    "毫秒镜像(推荐)@docker.1ms.run"
 | 
					    "毫秒镜像(推荐)@docker.1ms.run"
 | 
				
			||||||
    "Docker Proxy@dockerproxy.net"
 | 
					    "Docker Proxy@dockerproxy.net"
 | 
				
			||||||
@@ -90,6 +90,7 @@ SYSTEM_CENTOS_STREAM="CentOS Stream"
 | 
				
			|||||||
SYSTEM_ROCKY="Rocky"
 | 
					SYSTEM_ROCKY="Rocky"
 | 
				
			||||||
SYSTEM_ALMALINUX="AlmaLinux"
 | 
					SYSTEM_ALMALINUX="AlmaLinux"
 | 
				
			||||||
SYSTEM_FEDORA="Fedora"
 | 
					SYSTEM_FEDORA="Fedora"
 | 
				
			||||||
 | 
					SYSTEM_ORACLE="Oracle Linux"
 | 
				
			||||||
SYSTEM_OPENCLOUDOS="OpenCloudOS"
 | 
					SYSTEM_OPENCLOUDOS="OpenCloudOS"
 | 
				
			||||||
SYSTEM_OPENCLOUDOS_STREAM="OpenCloudOS Stream"
 | 
					SYSTEM_OPENCLOUDOS_STREAM="OpenCloudOS Stream"
 | 
				
			||||||
SYSTEM_OPENEULER="openEuler"
 | 
					SYSTEM_OPENEULER="openEuler"
 | 
				
			||||||
@@ -166,9 +167,7 @@ function main() {
 | 
				
			|||||||
    run_end
 | 
					    run_end
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 处理命令选项
 | 
					 | 
				
			||||||
function handle_command_options() {
 | 
					function handle_command_options() {
 | 
				
			||||||
    ## 命令帮助
 | 
					 | 
				
			||||||
    function output_command_help() {
 | 
					    function output_command_help() {
 | 
				
			||||||
        echo -e "
 | 
					        echo -e "
 | 
				
			||||||
命令选项(名称/含义/值):
 | 
					命令选项(名称/含义/值):
 | 
				
			||||||
@@ -198,13 +197,13 @@ function handle_command_options() {
 | 
				
			|||||||
            if [ "$2" ]; then
 | 
					            if [ "$2" ]; then
 | 
				
			||||||
                echo "$2" | grep -Eq "\(|\)|\[|\]|\{|\}"
 | 
					                echo "$2" | grep -Eq "\(|\)|\[|\]|\{|\}"
 | 
				
			||||||
                if [ $? -eq 0 ]; then
 | 
					                if [ $? -eq 0 ]; then
 | 
				
			||||||
                    output_error "命令选项 ${BLUE}$2${PLAIN} 无效,请在该选项后指定有效的地址!"
 | 
					                    command_error "$2" "有效的地址"
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                    SOURCE="$(echo "$2" | sed -e 's,^http[s]\?://,,g' -e 's,/$,,')"
 | 
					                    SOURCE="$(echo "$2" | sed -e 's,^http[s]\?://,,g' -e 's,/$,,')"
 | 
				
			||||||
                    shift
 | 
					                    shift
 | 
				
			||||||
                fi
 | 
					                fi
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                output_error "命令选项 ${BLUE}$1${PLAIN} 无效,请在该选项后指定软件源地址!"
 | 
					                command_error "$1" "软件源地址"
 | 
				
			||||||
            fi
 | 
					            fi
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
        ## 指定 Docker Registry 仓库地址
 | 
					        ## 指定 Docker Registry 仓库地址
 | 
				
			||||||
@@ -212,13 +211,13 @@ function handle_command_options() {
 | 
				
			|||||||
            if [ "$2" ]; then
 | 
					            if [ "$2" ]; then
 | 
				
			||||||
                echo "$2" | grep -Eq "\(|\)|\[|\]|\{|\}"
 | 
					                echo "$2" | grep -Eq "\(|\)|\[|\]|\{|\}"
 | 
				
			||||||
                if [ $? -eq 0 ]; then
 | 
					                if [ $? -eq 0 ]; then
 | 
				
			||||||
                    output_error "命令选项 ${BLUE}$2${PLAIN} 无效,请在该选项后指定有效的地址!"
 | 
					                    command_error "$2" "有效的地址"
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                    SOURCE_REGISTRY="$(echo "$2" | sed -e 's,^http[s]\?://,,g' -e 's,/$,,')"
 | 
					                    SOURCE_REGISTRY="$(echo "$2" | sed -e 's,^http[s]\?://,,g' -e 's,/$,,')"
 | 
				
			||||||
                    shift
 | 
					                    shift
 | 
				
			||||||
                fi
 | 
					                fi
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                output_error "命令选项 ${BLUE}$1${PLAIN} 无效,请在该选项后指定镜像仓库地址!"
 | 
					                command_error "$1" "镜像仓库地址"
 | 
				
			||||||
            fi
 | 
					            fi
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
        ## 指定 Docker CE 软件源仓库
 | 
					        ## 指定 Docker CE 软件源仓库
 | 
				
			||||||
@@ -227,7 +226,7 @@ function handle_command_options() {
 | 
				
			|||||||
                SOURCE_BRANCH="$2"
 | 
					                SOURCE_BRANCH="$2"
 | 
				
			||||||
                shift
 | 
					                shift
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                output_error "命令选项 ${BLUE}$1${PLAIN} 无效,请在该选项后指定软件源仓库!"
 | 
					                command_error "$1" "软件源仓库"
 | 
				
			||||||
            fi
 | 
					            fi
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
        ## 指定 Debian 版本代号
 | 
					        ## 指定 Debian 版本代号
 | 
				
			||||||
@@ -236,7 +235,7 @@ function handle_command_options() {
 | 
				
			|||||||
                DEBIAN_CODENAME="$2"
 | 
					                DEBIAN_CODENAME="$2"
 | 
				
			||||||
                shift
 | 
					                shift
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                output_error "命令选项 ${BLUE}$1${PLAIN} 无效,请在该选项后指定版本代号!"
 | 
					                command_error "$1" "版本代号"
 | 
				
			||||||
            fi
 | 
					            fi
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
        ## 指定 Docker Engine 安装版本
 | 
					        ## 指定 Docker Engine 安装版本
 | 
				
			||||||
@@ -247,10 +246,10 @@ function handle_command_options() {
 | 
				
			|||||||
                    DESIGNATED_DOCKER_VERSION="$2"
 | 
					                    DESIGNATED_DOCKER_VERSION="$2"
 | 
				
			||||||
                    shift
 | 
					                    shift
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                    output_error "命令选项 ${BLUE}$2${PLAIN} 无效,请在该选项后指定有效的版本号!"
 | 
					                    command_error "$2" "有效的版本号"
 | 
				
			||||||
                fi
 | 
					                fi
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                output_error "命令选项 ${BLUE}$1${PLAIN} 无效,请在该选项后指定版本号!"
 | 
					                command_error "$1" "版本号"
 | 
				
			||||||
            fi
 | 
					            fi
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
        ## WEB 协议(HTTP/HTTPS)
 | 
					        ## WEB 协议(HTTP/HTTPS)
 | 
				
			||||||
@@ -262,11 +261,11 @@ function handle_command_options() {
 | 
				
			|||||||
                    shift
 | 
					                    shift
 | 
				
			||||||
                    ;;
 | 
					                    ;;
 | 
				
			||||||
                *)
 | 
					                *)
 | 
				
			||||||
                    output_error "检测到 ${BLUE}$2${PLAIN} 为无效参数值,请在该选项后指定 http 或 https !"
 | 
					                    command_error "$2" " http 或 https "
 | 
				
			||||||
                    ;;
 | 
					                    ;;
 | 
				
			||||||
                esac
 | 
					                esac
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                output_error "命令选项 ${BLUE}$1${PLAIN} 无效,请在该选项后指定 WEB 协议(http/https)!"
 | 
					                ocommand_error "$1" " WEB 协议 (http/https) "
 | 
				
			||||||
            fi
 | 
					            fi
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
        ## 安装最新版本
 | 
					        ## 安装最新版本
 | 
				
			||||||
@@ -278,11 +277,11 @@ function handle_command_options() {
 | 
				
			|||||||
                    shift
 | 
					                    shift
 | 
				
			||||||
                    ;;
 | 
					                    ;;
 | 
				
			||||||
                *)
 | 
					                *)
 | 
				
			||||||
                    output_error "命令选项 ${BLUE}$2${PLAIN} 无效,请在该选项后指定 true 或 false !"
 | 
					                    command_error "$2" " true 或 false "
 | 
				
			||||||
                    ;;
 | 
					                    ;;
 | 
				
			||||||
                esac
 | 
					                esac
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                output_error "命令选项 ${BLUE}$1${PLAIN} 无效,请在该选项后指定 true 或 false !"
 | 
					                command_error "$1" " true 或 false "
 | 
				
			||||||
            fi
 | 
					            fi
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
        ## 忽略覆盖备份提示
 | 
					        ## 忽略覆盖备份提示
 | 
				
			||||||
@@ -298,11 +297,11 @@ function handle_command_options() {
 | 
				
			|||||||
                    shift
 | 
					                    shift
 | 
				
			||||||
                    ;;
 | 
					                    ;;
 | 
				
			||||||
                *)
 | 
					                *)
 | 
				
			||||||
                    output_error "命令选项 ${BLUE}$2${PLAIN} 无效,请在该选项后指定 true 或 false !"
 | 
					                    command_error "$2" " true 或 false "
 | 
				
			||||||
                    ;;
 | 
					                    ;;
 | 
				
			||||||
                esac
 | 
					                esac
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                output_error "命令选项 ${BLUE}$1${PLAIN} 无效,请在该选项后指定 true 或 false !"
 | 
					                command_error "$1" " true 或 false "
 | 
				
			||||||
            fi
 | 
					            fi
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
        ## 清除屏幕上的所有内容
 | 
					        ## 清除屏幕上的所有内容
 | 
				
			||||||
@@ -314,11 +313,11 @@ function handle_command_options() {
 | 
				
			|||||||
                    shift
 | 
					                    shift
 | 
				
			||||||
                    ;;
 | 
					                    ;;
 | 
				
			||||||
                *)
 | 
					                *)
 | 
				
			||||||
                    output_error "命令选项 ${BLUE}$2${PLAIN} 无效,请在该选项后指定 true 或 false !"
 | 
					                    command_error "$2" " true 或 false "
 | 
				
			||||||
                    ;;
 | 
					                    ;;
 | 
				
			||||||
                esac
 | 
					                esac
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                output_error "命令选项 ${BLUE}$1${PLAIN} 无效,请在该选项后指定 true 或 false !"
 | 
					                command_error "$1" " true 或 false "
 | 
				
			||||||
            fi
 | 
					            fi
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
        ## 仅更换镜像仓库模式
 | 
					        ## 仅更换镜像仓库模式
 | 
				
			||||||
@@ -335,7 +334,7 @@ function handle_command_options() {
 | 
				
			|||||||
            exit
 | 
					            exit
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
        *)
 | 
					        *)
 | 
				
			||||||
            output_error "命令选项 ${BLUE}$1${PLAIN} 无效,请确认后重新输入!"
 | 
					            command_error "$1"
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
        esac
 | 
					        esac
 | 
				
			||||||
        shift
 | 
					        shift
 | 
				
			||||||
@@ -364,7 +363,6 @@ function run_start() {
 | 
				
			|||||||
    echo -e "欢迎使用 Docker Engine 安装与换源脚本"
 | 
					    echo -e "欢迎使用 Docker Engine 安装与换源脚本"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 运行结束
 | 
					 | 
				
			||||||
function run_end() {
 | 
					function run_end() {
 | 
				
			||||||
    if [[ "${PURE_MODE}" == "true" ]]; then
 | 
					    if [[ "${PURE_MODE}" == "true" ]]; then
 | 
				
			||||||
        echo ''
 | 
					        echo ''
 | 
				
			||||||
@@ -381,25 +379,41 @@ function run_end() {
 | 
				
			|||||||
    echo -e "\n\033[3;1mPowered by \033[34mLinuxMirrors\033[0m\n"
 | 
					    echo -e "\n\033[3;1mPowered by \033[34mLinuxMirrors\033[0m\n"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 报错退出
 | 
					 | 
				
			||||||
function output_error() {
 | 
					function output_error() {
 | 
				
			||||||
    [ "$1" ] && echo -e "\n$ERROR $1\n"
 | 
					    [ "$1" ] && echo -e "\n$ERROR $1\n"
 | 
				
			||||||
    exit 1
 | 
					    exit 1
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 检查命令是否存在
 | 
					function command_error() {
 | 
				
			||||||
 | 
					    local tmp_text="请确认后重新输入"
 | 
				
			||||||
 | 
					    if [[ "${2}" ]]; then
 | 
				
			||||||
 | 
					        tmp_text="请在该选项后指定${2}"
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    output_error "命令选项 ${BLUE}$1${PLAIN} 无效,${tmp_text}!"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function unsupport_system_error() {
 | 
				
			||||||
 | 
					    local tmp_text=""
 | 
				
			||||||
 | 
					    if [[ "${2}" ]]; then
 | 
				
			||||||
 | 
					        tmp_text=",请参考如下命令自行安装:\n\n${BLUE}$2${PLAIN}"
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    output_error "不支持当前操作系统($1)${tmp_text}"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function input_error() {
 | 
				
			||||||
 | 
					    echo -e "\n$WARN 输入错误,$1!"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function command_exists() {
 | 
					function command_exists() {
 | 
				
			||||||
    command -v "$@" &>/dev/null
 | 
					    command -v "$@" &>/dev/null
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 权限判定
 | 
					 | 
				
			||||||
function permission_judgment() {
 | 
					function permission_judgment() {
 | 
				
			||||||
    if [ $UID -ne 0 ]; then
 | 
					    if [ $UID -ne 0 ]; then
 | 
				
			||||||
        output_error "权限不足,请使用 Root 用户运行本脚本"
 | 
					        output_error "权限不足,请使用 Root 用户运行本脚本"
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 收集系统信息
 | 
					 | 
				
			||||||
function collect_system_info() {
 | 
					function collect_system_info() {
 | 
				
			||||||
    ## 定义系统名称
 | 
					    ## 定义系统名称
 | 
				
			||||||
    SYSTEM_NAME="$(cat $File_LinuxRelease | grep -E "^NAME=" | awk -F '=' '{print$2}' | sed "s/[\'\"]//g")"
 | 
					    SYSTEM_NAME="$(cat $File_LinuxRelease | grep -E "^NAME=" | awk -F '=' '{print$2}' | sed "s/[\'\"]//g")"
 | 
				
			||||||
@@ -413,8 +427,6 @@ function collect_system_info() {
 | 
				
			|||||||
    ## 判定当前系统派系
 | 
					    ## 判定当前系统派系
 | 
				
			||||||
    if [ -s "${File_DebianVersion}" ]; then
 | 
					    if [ -s "${File_DebianVersion}" ]; then
 | 
				
			||||||
        SYSTEM_FACTIONS="${SYSTEM_DEBIAN}"
 | 
					        SYSTEM_FACTIONS="${SYSTEM_DEBIAN}"
 | 
				
			||||||
    elif [ -s "${File_OracleLinuxRelease}" ]; then
 | 
					 | 
				
			||||||
        [[ "${ONLY_REGISTRY}" != "true" ]] && output_error "不支持当前操作系统,请参考如下命令自行安装:\n\ndnf install -y docker\nsystemctl enable --now docker"
 | 
					 | 
				
			||||||
    elif [ -s "${File_RedHatRelease}" ]; then
 | 
					    elif [ -s "${File_RedHatRelease}" ]; then
 | 
				
			||||||
        SYSTEM_FACTIONS="${SYSTEM_REDHAT}"
 | 
					        SYSTEM_FACTIONS="${SYSTEM_REDHAT}"
 | 
				
			||||||
    elif [ -s "${File_openEulerRelease}" ]; then
 | 
					    elif [ -s "${File_openEulerRelease}" ]; then
 | 
				
			||||||
@@ -422,27 +434,27 @@ function collect_system_info() {
 | 
				
			|||||||
    elif [ -s "${File_OpenCloudOSRelease}" ]; then
 | 
					    elif [ -s "${File_OpenCloudOSRelease}" ]; then
 | 
				
			||||||
        # 拦截 OpenCloudOS 9 及以上版本,不支持从 Docker 官方仓库安装
 | 
					        # 拦截 OpenCloudOS 9 及以上版本,不支持从 Docker 官方仓库安装
 | 
				
			||||||
        if [[ "${SYSTEM_VERSION_ID_MAJOR}" -ge 9 ]]; then
 | 
					        if [[ "${SYSTEM_VERSION_ID_MAJOR}" -ge 9 ]]; then
 | 
				
			||||||
            [[ "${ONLY_REGISTRY}" != "true" ]] && output_error "不支持当前操作系统,请参考如下命令自行安装:\n\ndnf install -y docker\nsystemctl enable --now docker"
 | 
					            [[ "${ONLY_REGISTRY}" != "true" ]] && unsupport_system_error "OpenCloudOS 9" "dnf install -y docker\nsystemctl enable --now docker"
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
        SYSTEM_FACTIONS="${SYSTEM_OPENCLOUDOS}" # 自 9.0 版本起不再基于红帽
 | 
					        SYSTEM_FACTIONS="${SYSTEM_OPENCLOUDOS}" # 自 9.0 版本起不再基于红帽
 | 
				
			||||||
    elif [ -s "${File_AnolisOSRelease}" ]; then
 | 
					    elif [ -s "${File_AnolisOSRelease}" ]; then
 | 
				
			||||||
        # 拦截 Anolis OS 8.8 及以上版本,不支持从 Docker 官方仓库安装,23 版本支持
 | 
					        # 拦截 Anolis OS 8.8 及以上版本,不支持从 Docker 官方仓库安装,23 版本支持
 | 
				
			||||||
        if [[ "${SYSTEM_VERSION_ID_MAJOR}" == 8 ]]; then
 | 
					        if [[ "${SYSTEM_VERSION_ID_MAJOR}" == 8 ]]; then
 | 
				
			||||||
            [[ "${ONLY_REGISTRY}" != "true" ]] && output_error "不支持当前操作系统,请参考如下命令自行安装:\n\ndnf install -y docker\nsystemctl enable --now docker"
 | 
					            [[ "${ONLY_REGISTRY}" != "true" ]] && unsupport_system_error "Anolis OS 8" "dnf install -y docker\nsystemctl enable --now docker"
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
        SYSTEM_FACTIONS="${SYSTEM_ANOLISOS}" # 自 8.8 版本起不再基于红帽
 | 
					        SYSTEM_FACTIONS="${SYSTEM_ANOLISOS}" # 自 8.8 版本起不再基于红帽
 | 
				
			||||||
    elif [ -s "${File_openKylinVersion}" ]; then
 | 
					    elif [ -s "${File_openKylinVersion}" ]; then
 | 
				
			||||||
        [[ "${ONLY_REGISTRY}" != "true" ]] && output_error "不支持当前操作系统,请参考如下命令自行安装:\n\napt-get install -y docker\nsystemctl enable --now docker"
 | 
					        [[ "${ONLY_REGISTRY}" != "true" ]] && unsupport_system_error "openKylin" "apt-get install -y docker\nsystemctl enable --now docker"
 | 
				
			||||||
    elif [ -f "${File_ArchLinuxRelease}" ]; then
 | 
					    elif [ -f "${File_ArchLinuxRelease}" ]; then
 | 
				
			||||||
        [[ "${ONLY_REGISTRY}" != "true" ]] && output_error "不支持当前操作系统,请参考如下命令自行安装:\n\npacman -S docker\nsystemctl enable --now docker"
 | 
					        [[ "${ONLY_REGISTRY}" != "true" ]] && unsupport_system_error "Arch Linux" "pacman -S docker\nsystemctl enable --now docker"
 | 
				
			||||||
    elif [ -f "${File_GentooRelease}" ]; then
 | 
					    elif [ -f "${File_GentooRelease}" ]; then
 | 
				
			||||||
        [[ "${ONLY_REGISTRY}" != "true" ]] && output_error "不支持当前操作系统(Gentoo)"
 | 
					        [[ "${ONLY_REGISTRY}" != "true" ]] && unsupport_system_error "Gentoo"
 | 
				
			||||||
    elif [[ "${SYSTEM_NAME}" == *"openSUSE"* ]]; then
 | 
					    elif [[ "${SYSTEM_NAME}" == *"openSUSE"* ]]; then
 | 
				
			||||||
        [[ "${ONLY_REGISTRY}" != "true" ]] && output_error "不支持当前操作系统,请参考如下命令自行安装:\n\nzypper install docker\nsystemctl enable --now docker"
 | 
					        [[ "${ONLY_REGISTRY}" != "true" ]] && unsupport_system_error "openSUSE" "zypper install docker\nsystemctl enable --now docker"
 | 
				
			||||||
    elif [[ "${SYSTEM_NAME}" == *"NixOS"* ]]; then
 | 
					    elif [[ "${SYSTEM_NAME}" == *"NixOS"* ]]; then
 | 
				
			||||||
        [[ "${ONLY_REGISTRY}" != "true" ]] && output_error "不支持当前操作系统(NixOS)"
 | 
					        [[ "${ONLY_REGISTRY}" != "true" ]] && unsupport_system_error "NixOS"
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        output_error "不支持当前操作系统"
 | 
					        unsupport_system_error "未知的系统"
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
    ## 判定系统类型、版本、版本号
 | 
					    ## 判定系统类型、版本、版本号
 | 
				
			||||||
    case "${SYSTEM_FACTIONS}" in
 | 
					    case "${SYSTEM_FACTIONS}" in
 | 
				
			||||||
@@ -466,13 +478,15 @@ function collect_system_info() {
 | 
				
			|||||||
        SYSTEM_JUDGMENT="$(awk '{printf $1}' $File_RedHatRelease)"
 | 
					        SYSTEM_JUDGMENT="$(awk '{printf $1}' $File_RedHatRelease)"
 | 
				
			||||||
        # 拦截 Anolis OS 8.8 以下版本,不支持从 Docker 官方仓库安装
 | 
					        # 拦截 Anolis OS 8.8 以下版本,不支持从 Docker 官方仓库安装
 | 
				
			||||||
        if [[ "${SYSTEM_JUDGMENT}" == "${SYSTEM_ANOLISOS}" ]]; then
 | 
					        if [[ "${SYSTEM_JUDGMENT}" == "${SYSTEM_ANOLISOS}" ]]; then
 | 
				
			||||||
            [[ "${ONLY_REGISTRY}" != "true" ]] && output_error "不支持当前操作系统,请参考如下命令自行安装:\n\ndnf install -y docker\nsystemctl enable --now docker"
 | 
					            [[ "${ONLY_REGISTRY}" != "true" ]] && unsupport_system_error "Anolis OS 8" "dnf install -y docker\nsystemctl enable --now docker"
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
        ## 特殊系统判断
 | 
					        ## 特殊系统判断
 | 
				
			||||||
        # Red Hat Enterprise Linux
 | 
					        # Red Hat Enterprise Linux
 | 
				
			||||||
        grep -q "${SYSTEM_RHEL}" $File_RedHatRelease && SYSTEM_JUDGMENT="${SYSTEM_RHEL}"
 | 
					        grep -q "${SYSTEM_RHEL}" $File_RedHatRelease && SYSTEM_JUDGMENT="${SYSTEM_RHEL}"
 | 
				
			||||||
        # CentOS Stream
 | 
					        # CentOS Stream
 | 
				
			||||||
        grep -q "${SYSTEM_CENTOS_STREAM}" $File_RedHatRelease && SYSTEM_JUDGMENT="${SYSTEM_CENTOS_STREAM}"
 | 
					        grep -q "${SYSTEM_CENTOS_STREAM}" $File_RedHatRelease && SYSTEM_JUDGMENT="${SYSTEM_CENTOS_STREAM}"
 | 
				
			||||||
 | 
					        # Oracle Linux
 | 
				
			||||||
 | 
					        [ -s "${File_OracleLinuxRelease}" ] && SYSTEM_JUDGMENT="${SYSTEM_ORACLE}"
 | 
				
			||||||
        ;;
 | 
					        ;;
 | 
				
			||||||
    *)
 | 
					    *)
 | 
				
			||||||
        SYSTEM_JUDGMENT="${SYSTEM_FACTIONS}"
 | 
					        SYSTEM_JUDGMENT="${SYSTEM_FACTIONS}"
 | 
				
			||||||
@@ -547,9 +561,11 @@ function collect_system_info() {
 | 
				
			|||||||
                ;;
 | 
					                ;;
 | 
				
			||||||
            "${SYSTEM_RHEL}")
 | 
					            "${SYSTEM_RHEL}")
 | 
				
			||||||
                SOURCE_BRANCH="rhel"
 | 
					                SOURCE_BRANCH="rhel"
 | 
				
			||||||
                # 拦截 RHEL 最新的 10 版本
 | 
					                # RHEL 10
 | 
				
			||||||
                if [[ "${SYSTEM_VERSION_ID_MAJOR}" == 10 ]]; then
 | 
					                if [[ "${SYSTEM_VERSION_ID_MAJOR}" == 10 ]]; then
 | 
				
			||||||
                    output_error "暂不支持当前操作系统(RHEL 10),请等待 Docker 官方适配或使用正版操作系统软件源进行安装"
 | 
					                    echo -e "\n$WARN 当前采用 centos 分支(红帽衍生操作系统安装方式)进行安装,可能存在某些无法预料的兼容性问题!"
 | 
				
			||||||
 | 
					                    echo -e "\n$TIP Docker 官方尚未支持 RHEL 10 且红帽官方已将 Docker 从注册软件源中移除并默认使用 Podman。"
 | 
				
			||||||
 | 
					                    SOURCE_BRANCH="centos"
 | 
				
			||||||
                fi
 | 
					                fi
 | 
				
			||||||
                ;;
 | 
					                ;;
 | 
				
			||||||
            *)
 | 
					            *)
 | 
				
			||||||
@@ -706,16 +722,17 @@ function choose_protocol() {
 | 
				
			|||||||
        if [[ "${ONLY_HTTP}" == "true" ]]; then
 | 
					        if [[ "${ONLY_HTTP}" == "true" ]]; then
 | 
				
			||||||
            WEB_PROTOCOL="http"
 | 
					            WEB_PROTOCOL="http"
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
 | 
					            local ask_text="软件源是否使用 HTTP 协议?"
 | 
				
			||||||
            if [[ "${CAN_USE_ADVANCED_INTERACTIVE_SELECTION}" == "true" ]]; then
 | 
					            if [[ "${CAN_USE_ADVANCED_INTERACTIVE_SELECTION}" == "true" ]]; then
 | 
				
			||||||
                echo ''
 | 
					                echo ''
 | 
				
			||||||
                interactive_select_boolean "${BOLD}软件源是否使用 HTTP 协议?${PLAIN}"
 | 
					                interactive_select_boolean "${BOLD}${ask_text}${PLAIN}"
 | 
				
			||||||
                if [[ "${_SELECT_RESULT}" == "true" ]]; then
 | 
					                if [[ "${_SELECT_RESULT}" == "true" ]]; then
 | 
				
			||||||
                    WEB_PROTOCOL="http"
 | 
					                    WEB_PROTOCOL="http"
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                    WEB_PROTOCOL="https"
 | 
					                    WEB_PROTOCOL="https"
 | 
				
			||||||
                fi
 | 
					                fi
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                local CHOICE=$(echo -e "\n${BOLD}└─ 软件源是否使用 HTTP 协议? [Y/n] ${PLAIN}")
 | 
					                local CHOICE="$(echo -e "\n${BOLD}└─ ${ask_text} [Y/n] ${PLAIN}")"
 | 
				
			||||||
                read -rp "${CHOICE}" INPUT
 | 
					                read -rp "${CHOICE}" INPUT
 | 
				
			||||||
                [[ -z "${INPUT}" ]] && INPUT=Y
 | 
					                [[ -z "${INPUT}" ]] && INPUT=Y
 | 
				
			||||||
                case "${INPUT}" in
 | 
					                case "${INPUT}" in
 | 
				
			||||||
@@ -726,7 +743,7 @@ function choose_protocol() {
 | 
				
			|||||||
                    WEB_PROTOCOL="https"
 | 
					                    WEB_PROTOCOL="https"
 | 
				
			||||||
                    ;;
 | 
					                    ;;
 | 
				
			||||||
                *)
 | 
					                *)
 | 
				
			||||||
                    echo -e "\n$WARN 输入错误,默认使用 HTTPS 协议!"
 | 
					                    input_error "默认使用 HTTPS 协议"
 | 
				
			||||||
                    WEB_PROTOCOL="https"
 | 
					                    WEB_PROTOCOL="https"
 | 
				
			||||||
                    ;;
 | 
					                    ;;
 | 
				
			||||||
                esac
 | 
					                esac
 | 
				
			||||||
@@ -743,14 +760,15 @@ function close_firewall_service() {
 | 
				
			|||||||
    fi
 | 
					    fi
 | 
				
			||||||
    if [[ "$(systemctl is-active firewalld)" == "active" ]]; then
 | 
					    if [[ "$(systemctl is-active firewalld)" == "active" ]]; then
 | 
				
			||||||
        if [[ -z "${CLOSE_FIREWALL}" ]]; then
 | 
					        if [[ -z "${CLOSE_FIREWALL}" ]]; then
 | 
				
			||||||
 | 
					            local ask_text="是否关闭系统防火墙和 SELinux ?"
 | 
				
			||||||
            if [[ "${CAN_USE_ADVANCED_INTERACTIVE_SELECTION}" == "true" ]]; then
 | 
					            if [[ "${CAN_USE_ADVANCED_INTERACTIVE_SELECTION}" == "true" ]]; then
 | 
				
			||||||
                echo ''
 | 
					                echo ''
 | 
				
			||||||
                interactive_select_boolean "${BOLD}是否关闭系统防火墙和 SELinux ?${PLAIN}"
 | 
					                interactive_select_boolean "${BOLD}${ask_text}${PLAIN}"
 | 
				
			||||||
                if [[ "${_SELECT_RESULT}" == "true" ]]; then
 | 
					                if [[ "${_SELECT_RESULT}" == "true" ]]; then
 | 
				
			||||||
                    CLOSE_FIREWALL="true"
 | 
					                    CLOSE_FIREWALL="true"
 | 
				
			||||||
                fi
 | 
					                fi
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                local CHOICE=$(echo -e "\n${BOLD}└─ 是否关闭系统防火墙和 SELinux ? [Y/n] ${PLAIN}")
 | 
					                local CHOICE="$(echo -e "\n${BOLD}└─ ${ask_text} [Y/n] ${PLAIN}")"
 | 
				
			||||||
                read -rp "${CHOICE}" INPUT
 | 
					                read -rp "${CHOICE}" INPUT
 | 
				
			||||||
                [[ -z "${INPUT}" ]] && INPUT=Y
 | 
					                [[ -z "${INPUT}" ]] && INPUT=Y
 | 
				
			||||||
                case "${INPUT}" in
 | 
					                case "${INPUT}" in
 | 
				
			||||||
@@ -759,7 +777,7 @@ function close_firewall_service() {
 | 
				
			|||||||
                    ;;
 | 
					                    ;;
 | 
				
			||||||
                [Nn] | [Nn][Oo]) ;;
 | 
					                [Nn] | [Nn][Oo]) ;;
 | 
				
			||||||
                *)
 | 
					                *)
 | 
				
			||||||
                    echo -e "\n$WARN 输入错误,默认不关闭!"
 | 
					                    input_error "默认不关闭"
 | 
				
			||||||
                    ;;
 | 
					                    ;;
 | 
				
			||||||
                esac
 | 
					                esac
 | 
				
			||||||
            fi
 | 
					            fi
 | 
				
			||||||
@@ -1004,7 +1022,7 @@ function install_docker_engine() {
 | 
				
			|||||||
                    target_docker_version="${_SELECT_RESULT}"
 | 
					                    target_docker_version="${_SELECT_RESULT}"
 | 
				
			||||||
                    echo -e "\n${GREEN}➜${PLAIN}  ${BOLD}指定安装版本:${target_docker_version}${PLAIN}\n"
 | 
					                    echo -e "\n${GREEN}➜${PLAIN}  ${BOLD}指定安装版本:${target_docker_version}${PLAIN}\n"
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                    echo -e "\n${GREEN} --------- 请选择你要安装的版本,如:27.4.0 ---------- ${PLAIN}\n"
 | 
					                    echo -e "\n${GREEN} --------- 请选择你要安装的版本,如:28.3.0 ---------- ${PLAIN}\n"
 | 
				
			||||||
                    cat $File_DockerVersionTmp
 | 
					                    cat $File_DockerVersionTmp
 | 
				
			||||||
                    while true; do
 | 
					                    while true; do
 | 
				
			||||||
                        local CHOICE=$(echo -e "\n${BOLD}└─ 请根据上面的列表,选择并输入你想要安装的具体版本号:${PLAIN}\n")
 | 
					                        local CHOICE=$(echo -e "\n${BOLD}└─ 请根据上面的列表,选择并输入你想要安装的具体版本号:${PLAIN}\n")
 | 
				
			||||||
@@ -1080,16 +1098,17 @@ function install_docker_engine() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ## 判断是否手动选择安装版本
 | 
					    ## 判断是否手动选择安装版本
 | 
				
			||||||
    if [[ -z "${INSTALL_LATESTED_DOCKER}" ]]; then
 | 
					    if [[ -z "${INSTALL_LATESTED_DOCKER}" ]]; then
 | 
				
			||||||
 | 
					        local ask_text="是否安装最新版本的 Docker Engine ?"
 | 
				
			||||||
        if [[ "${CAN_USE_ADVANCED_INTERACTIVE_SELECTION}" == "true" ]]; then
 | 
					        if [[ "${CAN_USE_ADVANCED_INTERACTIVE_SELECTION}" == "true" ]]; then
 | 
				
			||||||
            echo ''
 | 
					            echo ''
 | 
				
			||||||
            interactive_select_boolean "${BOLD}是否安装最新版本的 Docker Engine ?${PLAIN}"
 | 
					            interactive_select_boolean "${BOLD}${ask_text}${PLAIN}"
 | 
				
			||||||
            if [[ "${_SELECT_RESULT}" == "true" ]]; then
 | 
					            if [[ "${_SELECT_RESULT}" == "true" ]]; then
 | 
				
			||||||
                INSTALL_LATESTED_DOCKER="true"
 | 
					                INSTALL_LATESTED_DOCKER="true"
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                INSTALL_LATESTED_DOCKER="false"
 | 
					                INSTALL_LATESTED_DOCKER="false"
 | 
				
			||||||
            fi
 | 
					            fi
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            local CHOICE_A=$(echo -e "\n${BOLD}└─ 是否安装最新版本的 Docker Engine ? [Y/n] ${PLAIN}")
 | 
					            local CHOICE_A="$(echo -e "\n${BOLD}└─ ${ask_text} [Y/n] ${PLAIN}")"
 | 
				
			||||||
            read -p "${CHOICE_A}" INPUT
 | 
					            read -p "${CHOICE_A}" INPUT
 | 
				
			||||||
            [[ -z "${INPUT}" ]] && INPUT=Y
 | 
					            [[ -z "${INPUT}" ]] && INPUT=Y
 | 
				
			||||||
            case $INPUT in
 | 
					            case $INPUT in
 | 
				
			||||||
@@ -1101,10 +1120,11 @@ function install_docker_engine() {
 | 
				
			|||||||
                ;;
 | 
					                ;;
 | 
				
			||||||
            *)
 | 
					            *)
 | 
				
			||||||
                INSTALL_LATESTED_DOCKER="true"
 | 
					                INSTALL_LATESTED_DOCKER="true"
 | 
				
			||||||
                echo -e "\n$WARN 输入错误,默认安装最新版本!"
 | 
					                input_error "默认安装最新版本"
 | 
				
			||||||
                ;;
 | 
					                ;;
 | 
				
			||||||
            esac
 | 
					            esac
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
 | 
					        echo ''
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ## 判定是否已安装
 | 
					    ## 判定是否已安装
 | 
				
			||||||
@@ -1158,15 +1178,16 @@ function change_docker_registry_mirror() {
 | 
				
			|||||||
    if [ -d "${Dir_Docker}" ] && [ -e "${File_DockerConfig}" ]; then
 | 
					    if [ -d "${Dir_Docker}" ] && [ -e "${File_DockerConfig}" ]; then
 | 
				
			||||||
        if [ -e "${File_DockerConfigBackup}" ]; then
 | 
					        if [ -e "${File_DockerConfigBackup}" ]; then
 | 
				
			||||||
            if [[ "${IGNORE_BACKUP_TIPS}" == "false" ]]; then
 | 
					            if [[ "${IGNORE_BACKUP_TIPS}" == "false" ]]; then
 | 
				
			||||||
 | 
					                local ask_text="检测到已备份的 Docker 配置文件,是否跳过覆盖备份?"
 | 
				
			||||||
                if [[ "${CAN_USE_ADVANCED_INTERACTIVE_SELECTION}" == "true" ]]; then
 | 
					                if [[ "${CAN_USE_ADVANCED_INTERACTIVE_SELECTION}" == "true" ]]; then
 | 
				
			||||||
                    echo ''
 | 
					                    echo ''
 | 
				
			||||||
                    interactive_select_boolean "${BOLD}检测到已备份的 Docker 配置文件,是否跳过覆盖备份?${PLAIN}"
 | 
					                    interactive_select_boolean "${BOLD}${ask_text}${PLAIN}"
 | 
				
			||||||
                    if [[ "${_SELECT_RESULT}" == "false" ]]; then
 | 
					                    if [[ "${_SELECT_RESULT}" == "false" ]]; then
 | 
				
			||||||
                        echo ''
 | 
					                        echo ''
 | 
				
			||||||
                        cp -rvf $File_DockerConfig $File_DockerConfigBackup 2>&1
 | 
					                        cp -rvf $File_DockerConfig $File_DockerConfigBackup 2>&1
 | 
				
			||||||
                    fi
 | 
					                    fi
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                    local CHOICE_BACKUP=$(echo -e "\n${BOLD}└─ 检测到已备份的 Docker 配置文件,是否跳过覆盖备份? [Y/n] ${PLAIN}")
 | 
					                    local CHOICE_BACKUP="$(echo -e "\n${BOLD}└─ ${ask_text} [Y/n] ${PLAIN}")"
 | 
				
			||||||
                    read -p "${CHOICE_BACKUP}" INPUT
 | 
					                    read -p "${CHOICE_BACKUP}" INPUT
 | 
				
			||||||
                    [[ -z "${INPUT}" ]] && INPUT=Y
 | 
					                    [[ -z "${INPUT}" ]] && INPUT=Y
 | 
				
			||||||
                    case $INPUT in
 | 
					                    case $INPUT in
 | 
				
			||||||
@@ -1176,7 +1197,7 @@ function change_docker_registry_mirror() {
 | 
				
			|||||||
                        cp -rvf $File_DockerConfig $File_DockerConfigBackup 2>&1
 | 
					                        cp -rvf $File_DockerConfig $File_DockerConfigBackup 2>&1
 | 
				
			||||||
                        ;;
 | 
					                        ;;
 | 
				
			||||||
                    *)
 | 
					                    *)
 | 
				
			||||||
                        echo -e "\n$WARN 输入错误,默认不覆盖!"
 | 
					                        input_error "默认不覆盖"
 | 
				
			||||||
                        ;;
 | 
					                        ;;
 | 
				
			||||||
                    esac
 | 
					                    esac
 | 
				
			||||||
                fi
 | 
					                fi
 | 
				
			||||||
@@ -1289,18 +1310,20 @@ function check_installed_result() {
 | 
				
			|||||||
            echo -e "              $(docker compose version 2>&1)"
 | 
					            echo -e "              $(docker compose version 2>&1)"
 | 
				
			||||||
            # echo -e "\n$COMPLETE 安装完成"
 | 
					            # echo -e "\n$COMPLETE 安装完成"
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            echo -e "\n$ERROR 安装失败"
 | 
					            echo -e "\n$FAIL 安装失败"
 | 
				
			||||||
 | 
					            local source_file package_manager
 | 
				
			||||||
            case "${SYSTEM_FACTIONS}" in
 | 
					            case "${SYSTEM_FACTIONS}" in
 | 
				
			||||||
            "${SYSTEM_DEBIAN}")
 | 
					            "${SYSTEM_DEBIAN}")
 | 
				
			||||||
                echo -e "\n检查源文件:cat $Dir_AptAdditionalSources/docker.list"
 | 
					                source_file="${Dir_AptAdditionalSources}/docker.list"
 | 
				
			||||||
                echo -e '请尝试手动执行安装命令:apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin\n'
 | 
					                package_manager="apt-get"
 | 
				
			||||||
                ;;
 | 
					                ;;
 | 
				
			||||||
            "${SYSTEM_REDHAT}" | "${SYSTEM_OPENEULER}" | "${SYSTEM_OPENCLOUDOS}" | "${SYSTEM_ANOLISOS}")
 | 
					            "${SYSTEM_REDHAT}" | "${SYSTEM_OPENEULER}" | "${SYSTEM_OPENCLOUDOS}" | "${SYSTEM_ANOLISOS}")
 | 
				
			||||||
                local package_manager="$(get_package_manager)"
 | 
					                source_file="${Dir_YumRepos}/docker.repo"
 | 
				
			||||||
                echo -e "\n检查源文件:cat ${Dir_YumRepos}/docker.repo"
 | 
					                package_manager="$(get_package_manager)"
 | 
				
			||||||
                echo -e "请尝试手动执行安装命令:${package_manager} install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin\n"
 | 
					 | 
				
			||||||
                ;;
 | 
					                ;;
 | 
				
			||||||
            esac
 | 
					            esac
 | 
				
			||||||
 | 
					            echo -e "\n检查源文件:cat ${source_file}"
 | 
				
			||||||
 | 
					            echo -e "请尝试手动执行安装命令:${package_manager} install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin\n"
 | 
				
			||||||
            exit 1
 | 
					            exit 1
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
        if [[ $(systemctl is-active docker) != "active" ]]; then
 | 
					        if [[ $(systemctl is-active docker) != "active" ]]; then
 | 
				
			||||||
@@ -1315,7 +1338,7 @@ function check_installed_result() {
 | 
				
			|||||||
            fi
 | 
					            fi
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        echo -e "\n$ERROR 安装失败"
 | 
					        echo -e "\n$FAIL 安装失败"
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1344,7 +1367,7 @@ function interactive_select_mirror() {
 | 
				
			|||||||
    unset options[${#options[@]}-1]
 | 
					    unset options[${#options[@]}-1]
 | 
				
			||||||
    local selected=0
 | 
					    local selected=0
 | 
				
			||||||
    local start=0
 | 
					    local start=0
 | 
				
			||||||
    local page_size=$(($(tput lines 2>/dev/null) - 3)) # 减去3行用于显示提示信息
 | 
					    local page_size=$(($(tput lines 2>/dev/null) - 3))
 | 
				
			||||||
    function clear_menu() {
 | 
					    function clear_menu() {
 | 
				
			||||||
        tput rc 2>/dev/null
 | 
					        tput rc 2>/dev/null
 | 
				
			||||||
        for ((i = 0; i < ${#options[@]} + 1; i++)); do
 | 
					        for ((i = 0; i < ${#options[@]} + 1; i++)); do
 | 
				
			||||||
@@ -1384,17 +1407,15 @@ function interactive_select_mirror() {
 | 
				
			|||||||
        fi
 | 
					        fi
 | 
				
			||||||
        echo "$key"
 | 
					        echo "$key"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    tput smcup 2>/dev/null  # 保存当前屏幕并切换到新屏幕
 | 
					    tput smcup 2>/dev/null
 | 
				
			||||||
    tput sc 2>/dev/null     # 保存光标位置
 | 
					    tput sc 2>/dev/null
 | 
				
			||||||
    tput civis 2>/dev/null  # 隐藏光标
 | 
					    tput civis 2>/dev/null
 | 
				
			||||||
    trap "cleanup" INT TERM # 捕捉脚本结束时恢复光标
 | 
					    trap "cleanup" INT TERM
 | 
				
			||||||
    draw_menu               # 初始化菜单位置
 | 
					    draw_menu
 | 
				
			||||||
    # 处理选择
 | 
					 | 
				
			||||||
    while true; do
 | 
					    while true; do
 | 
				
			||||||
        key=$(read_key)
 | 
					        key=$(read_key)
 | 
				
			||||||
        case "$key" in
 | 
					        case "$key" in
 | 
				
			||||||
        "[A" | "w" | "W")
 | 
					        "[A" | "w" | "W")
 | 
				
			||||||
            # 上箭头 / W
 | 
					 | 
				
			||||||
            if [ "$selected" -gt 0 ]; then
 | 
					            if [ "$selected" -gt 0 ]; then
 | 
				
			||||||
                selected=$((selected - 1))
 | 
					                selected=$((selected - 1))
 | 
				
			||||||
                if [ "$selected" -lt "$start" ]; then
 | 
					                if [ "$selected" -lt "$start" ]; then
 | 
				
			||||||
@@ -1403,7 +1424,6 @@ function interactive_select_mirror() {
 | 
				
			|||||||
            fi
 | 
					            fi
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
        "[B" | "s" | "S")
 | 
					        "[B" | "s" | "S")
 | 
				
			||||||
            # 下箭头 / S
 | 
					 | 
				
			||||||
            if [ "$selected" -lt $((${#options[@]} - 1)) ]; then
 | 
					            if [ "$selected" -lt $((${#options[@]} - 1)) ]; then
 | 
				
			||||||
                selected=$((selected + 1))
 | 
					                selected=$((selected + 1))
 | 
				
			||||||
                if [ "$selected" -ge $((start + page_size)) ]; then
 | 
					                if [ "$selected" -ge $((start + page_size)) ]; then
 | 
				
			||||||
@@ -1412,7 +1432,6 @@ function interactive_select_mirror() {
 | 
				
			|||||||
            fi
 | 
					            fi
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
        "")
 | 
					        "")
 | 
				
			||||||
            # Enter 键
 | 
					 | 
				
			||||||
            tput rmcup
 | 
					            tput rmcup
 | 
				
			||||||
            break
 | 
					            break
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
@@ -1420,11 +1439,8 @@ function interactive_select_mirror() {
 | 
				
			|||||||
        esac
 | 
					        esac
 | 
				
			||||||
        draw_menu
 | 
					        draw_menu
 | 
				
			||||||
    done
 | 
					    done
 | 
				
			||||||
    # clear_menu # 清除菜单
 | 
					    tput cnorm 2>/dev/null
 | 
				
			||||||
    tput cnorm 2>/dev/null # 恢复光标
 | 
					    tput rmcup 2>/dev/null
 | 
				
			||||||
    tput rmcup 2>/dev/null # 恢复之前的屏幕
 | 
					 | 
				
			||||||
    # tput rc 2>/dev/null # 恢复光标位置
 | 
					 | 
				
			||||||
    # 处理结果
 | 
					 | 
				
			||||||
    _SELECT_RESULT="${options[$selected]}"
 | 
					    _SELECT_RESULT="${options[$selected]}"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1432,17 +1448,15 @@ function interactive_select_boolean() {
 | 
				
			|||||||
    _SELECT_RESULT=""
 | 
					    _SELECT_RESULT=""
 | 
				
			||||||
    local selected=0
 | 
					    local selected=0
 | 
				
			||||||
    local message="$1"
 | 
					    local message="$1"
 | 
				
			||||||
    local menu_height=3 # 菜单总高度(标题行+空行+选项行)
 | 
					    local menu_height=3
 | 
				
			||||||
    local original_line
 | 
					    local original_line
 | 
				
			||||||
    function store_position() {
 | 
					    function store_position() {
 | 
				
			||||||
        # 保存菜单开始前的行位置
 | 
					 | 
				
			||||||
        original_line=$(tput lines 2>/dev/null)
 | 
					        original_line=$(tput lines 2>/dev/null)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    function clear_menu() {
 | 
					    function clear_menu() {
 | 
				
			||||||
        # 向上移动到菜单开始位置并清除菜单
 | 
					 | 
				
			||||||
        for ((i = 0; i < ${menu_height}; i++)); do
 | 
					        for ((i = 0; i < ${menu_height}; i++)); do
 | 
				
			||||||
            tput cuu1 2>/dev/null # 光标上移一行
 | 
					            tput cuu1 2>/dev/null
 | 
				
			||||||
            tput el 2>/dev/null   # 清除当前行
 | 
					            tput el 2>/dev/null
 | 
				
			||||||
        done
 | 
					        done
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    function cleanup() {
 | 
					    function cleanup() {
 | 
				
			||||||
@@ -1452,7 +1466,6 @@ function interactive_select_boolean() {
 | 
				
			|||||||
        exit 130
 | 
					        exit 130
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    function draw_menu() {
 | 
					    function draw_menu() {
 | 
				
			||||||
        # 绘制菜单不改变光标位置
 | 
					 | 
				
			||||||
        echo -e "╭─ ${message}"
 | 
					        echo -e "╭─ ${message}"
 | 
				
			||||||
        echo -e "│"
 | 
					        echo -e "│"
 | 
				
			||||||
        if [ "$selected" -eq 0 ]; then
 | 
					        if [ "$selected" -eq 0 ]; then
 | 
				
			||||||
@@ -1469,16 +1482,14 @@ function interactive_select_boolean() {
 | 
				
			|||||||
        fi
 | 
					        fi
 | 
				
			||||||
        echo "$key"
 | 
					        echo "$key"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    tput civis 2>/dev/null # 隐藏光标
 | 
					    tput civis 2>/dev/null
 | 
				
			||||||
    store_position         # 记录当前位置
 | 
					    store_position
 | 
				
			||||||
    trap "cleanup" INT TERM
 | 
					    trap "cleanup" INT TERM
 | 
				
			||||||
    draw_menu # 初始化菜单位置
 | 
					    draw_menu
 | 
				
			||||||
    # 处理选择
 | 
					 | 
				
			||||||
    while true; do
 | 
					    while true; do
 | 
				
			||||||
        key=$(read_key)
 | 
					        key=$(read_key)
 | 
				
			||||||
        case "$key" in
 | 
					        case "$key" in
 | 
				
			||||||
        "[D" | "a" | "A")
 | 
					        "[D" | "a" | "A")
 | 
				
			||||||
            # 左箭头 / A
 | 
					 | 
				
			||||||
            if [ "$selected" -gt 0 ]; then
 | 
					            if [ "$selected" -gt 0 ]; then
 | 
				
			||||||
                selected=$((selected - 1))
 | 
					                selected=$((selected - 1))
 | 
				
			||||||
                clear_menu
 | 
					                clear_menu
 | 
				
			||||||
@@ -1486,7 +1497,6 @@ function interactive_select_boolean() {
 | 
				
			|||||||
            fi
 | 
					            fi
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
        "[C" | "d" | "D")
 | 
					        "[C" | "d" | "D")
 | 
				
			||||||
            # 右箭头 / D
 | 
					 | 
				
			||||||
            if [ "$selected" -lt 1 ]; then
 | 
					            if [ "$selected" -lt 1 ]; then
 | 
				
			||||||
                selected=$((selected + 1))
 | 
					                selected=$((selected + 1))
 | 
				
			||||||
                clear_menu
 | 
					                clear_menu
 | 
				
			||||||
@@ -1494,8 +1504,7 @@ function interactive_select_boolean() {
 | 
				
			|||||||
            fi
 | 
					            fi
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
        "")
 | 
					        "")
 | 
				
			||||||
            # Enter 键
 | 
					            clear_menu
 | 
				
			||||||
            clear_menu # 先清除菜单
 | 
					 | 
				
			||||||
            break
 | 
					            break
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
        *) ;;
 | 
					        *) ;;
 | 
				
			||||||
@@ -1510,68 +1519,53 @@ function interactive_select_boolean() {
 | 
				
			|||||||
        echo -e "╰─ \033[2m○ 是 / \033[0m\033[32m●\033[0m \033[1m否\033[0m"
 | 
					        echo -e "╰─ \033[2m○ 是 / \033[0m\033[32m●\033[0m \033[1m否\033[0m"
 | 
				
			||||||
        _SELECT_RESULT="false"
 | 
					        _SELECT_RESULT="false"
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
    tput cnorm 2>/dev/null # 恢复光标
 | 
					    tput cnorm 2>/dev/null
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function animate_exec() {
 | 
					function animate_exec() {
 | 
				
			||||||
    local cmd="$1"
 | 
					    local cmd="$1"
 | 
				
			||||||
    local title="$2"
 | 
					    local title="$2"
 | 
				
			||||||
    local max_lines=${3:-5}          # 默认显示5行
 | 
					    local max_lines=${3:-5}
 | 
				
			||||||
    local spinner_style="${4:-dots}" # 动画样式
 | 
					    local spinner_style="${4:-dots}"
 | 
				
			||||||
    local refresh_rate="${5:-0.1}"   # 刷新率
 | 
					    local refresh_rate="${5:-0.1}"
 | 
				
			||||||
    # 动画样式
 | 
					 | 
				
			||||||
    local -A spinners=([dots]="⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏" [circle]="◐ ◓ ◑ ◒" [classic]="-\\ |/")
 | 
					    local -A spinners=([dots]="⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏" [circle]="◐ ◓ ◑ ◒" [classic]="-\\ |/")
 | 
				
			||||||
    local -A recommended_rates=([dots]="0.08" [circle]="0.12" [classic]="0.12")
 | 
					    local -A recommended_rates=([dots]="0.08" [circle]="0.12" [classic]="0.12")
 | 
				
			||||||
    [[ -z "${spinners[$spinner_style]}" ]] && spinner_style="dots"
 | 
					    [[ -z "${spinners[$spinner_style]}" ]] && spinner_style="dots"
 | 
				
			||||||
    [[ "${refresh_rate}" == "0.1" ]] && refresh_rate="${recommended_rates[$spinner_style]}"
 | 
					    [[ "${refresh_rate}" == "0.1" ]] && refresh_rate="${recommended_rates[$spinner_style]}"
 | 
				
			||||||
    # 获取终端宽度
 | 
					 | 
				
			||||||
    local term_width=$(tput cols 2>/dev/null || echo 80)
 | 
					    local term_width=$(tput cols 2>/dev/null || echo 80)
 | 
				
			||||||
    local display_width=$((term_width - 2))
 | 
					    local display_width=$((term_width - 2))
 | 
				
			||||||
    # 截断行
 | 
					 | 
				
			||||||
    function simple_truncate() {
 | 
					    function simple_truncate() {
 | 
				
			||||||
        local line="$1"
 | 
					        local line="$1"
 | 
				
			||||||
        local truncate_marker="..."
 | 
					        local truncate_marker="..."
 | 
				
			||||||
        local max_length=$((display_width - 3))
 | 
					        local max_length=$((display_width - 3))
 | 
				
			||||||
        # 快速判断:如果ASCII行长度在范围内,直接返回
 | 
					 | 
				
			||||||
        if [[ "${line}" =~ ^[[:ascii:]]*$ && ${#line} -le $display_width ]]; then
 | 
					        if [[ "${line}" =~ ^[[:ascii:]]*$ && ${#line} -le $display_width ]]; then
 | 
				
			||||||
            echo "${line}"
 | 
					            echo "${line}"
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
        # 1. 计算非ASCII字符数量
 | 
					 | 
				
			||||||
        local non_ascii_count=$(echo "${line// /}" | sed "s|[0-9a-zA-Z\.\=\:\_\(\)\'\"-\/\!·]||g;" | wc -m)
 | 
					        local non_ascii_count=$(echo "${line// /}" | sed "s|[0-9a-zA-Z\.\=\:\_\(\)\'\"-\/\!·]||g;" | wc -m)
 | 
				
			||||||
        # 2. 总字符数
 | 
					 | 
				
			||||||
        local total_length=${#line}
 | 
					        local total_length=${#line}
 | 
				
			||||||
        # 3. 实际显示宽度 = 总字符数 + 非ASCII字符数
 | 
					 | 
				
			||||||
        # 非ASCII字符额外占用1个宽度单位(即总共2个)
 | 
					 | 
				
			||||||
        local display_length=$((total_length + non_ascii_count))
 | 
					        local display_length=$((total_length + non_ascii_count))
 | 
				
			||||||
        # 4. 中文引号特殊处理(引号只占1个宽度,需要减去额外计算的部分)
 | 
					 | 
				
			||||||
        local quote_count=0
 | 
					        local quote_count=0
 | 
				
			||||||
        [[ $(echo "${line}" | grep -c "“") -gt 0 ]] && quote_count=$((quote_count + $(echo "${line}" | grep -c "“")))
 | 
					        [[ $(echo "${line}" | grep -c "“") -gt 0 ]] && quote_count=$((quote_count + $(echo "${line}" | grep -c "“")))
 | 
				
			||||||
        [[ $(echo "${line}" | grep -c "”") -gt 0 ]] && quote_count=$((quote_count + $(echo "${line}" | grep -c "”")))
 | 
					        [[ $(echo "${line}" | grep -c "”") -gt 0 ]] && quote_count=$((quote_count + $(echo "${line}" | grep -c "”")))
 | 
				
			||||||
        [[ $(echo "${line}" | grep -c "‘") -gt 0 ]] && quote_count=$((quote_count + $(echo "${line}" | grep -c "‘")))
 | 
					        [[ $(echo "${line}" | grep -c "‘") -gt 0 ]] && quote_count=$((quote_count + $(echo "${line}" | grep -c "‘")))
 | 
				
			||||||
        [[ $(echo "${line}" | grep -c "’") -gt 0 ]] && quote_count=$((quote_count + $(echo "${line}" | grep -c "’")))
 | 
					        [[ $(echo "${line}" | grep -c "’") -gt 0 ]] && quote_count=$((quote_count + $(echo "${line}" | grep -c "’")))
 | 
				
			||||||
        # 5. 调整宽度(减去引号额外计算的部分)
 | 
					 | 
				
			||||||
        display_length=$((display_length - quote_count))
 | 
					        display_length=$((display_length - quote_count))
 | 
				
			||||||
        # 如果计算宽度在显示范围内,直接显示
 | 
					 | 
				
			||||||
        if [[ $display_length -le $display_width ]]; then
 | 
					        if [[ $display_length -le $display_width ]]; then
 | 
				
			||||||
            echo "$line"
 | 
					            echo "$line"
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
        # 需要截断,逐字符构建
 | 
					 | 
				
			||||||
        local result=""
 | 
					        local result=""
 | 
				
			||||||
        local current_width=0
 | 
					        local current_width=0
 | 
				
			||||||
        local i=0
 | 
					        local i=0
 | 
				
			||||||
        while [ $i -lt ${#line} ]; do
 | 
					        while [ $i -lt ${#line} ]; do
 | 
				
			||||||
            local char="${line:$i:1}"
 | 
					            local char="${line:$i:1}"
 | 
				
			||||||
            local char_width=1
 | 
					            local char_width=1
 | 
				
			||||||
            # 是否是中文等宽字符(非ASCII)
 | 
					 | 
				
			||||||
            if ! [[ "$char" =~ [0-9a-zA-Z\.\=\:\_\(\)\'\"-\/\!·] ]]; then
 | 
					            if ! [[ "$char" =~ [0-9a-zA-Z\.\=\:\_\(\)\'\"-\/\!·] ]]; then
 | 
				
			||||||
                # 不是中文引号则算2个宽度
 | 
					 | 
				
			||||||
                if [[ "$char" != "“" && "$char" != "”" && "$char" != "‘" && "$char" != "’" ]]; then
 | 
					                if [[ "$char" != "“" && "$char" != "”" && "$char" != "‘" && "$char" != "’" ]]; then
 | 
				
			||||||
                    char_width=2
 | 
					                    char_width=2
 | 
				
			||||||
                fi
 | 
					                fi
 | 
				
			||||||
            fi
 | 
					            fi
 | 
				
			||||||
            # 检查添加此字符是否会超出限制
 | 
					 | 
				
			||||||
            if [[ $((current_width + char_width)) -gt $max_length ]]; then
 | 
					            if [[ $((current_width + char_width)) -gt $max_length ]]; then
 | 
				
			||||||
                echo "${result}${truncate_marker}"
 | 
					                echo "${result}${truncate_marker}"
 | 
				
			||||||
                return
 | 
					                return
 | 
				
			||||||
@@ -1580,17 +1574,14 @@ function animate_exec() {
 | 
				
			|||||||
            current_width=$((current_width + char_width))
 | 
					            current_width=$((current_width + char_width))
 | 
				
			||||||
            ((i++))
 | 
					            ((i++))
 | 
				
			||||||
        done
 | 
					        done
 | 
				
			||||||
        # 完整遍历未超出限制
 | 
					 | 
				
			||||||
        echo "${line}"
 | 
					        echo "${line}"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    # 清理函数
 | 
					 | 
				
			||||||
    function cleanup() {
 | 
					    function cleanup() {
 | 
				
			||||||
        [ -f "${temp_file}" ] && rm -f "${temp_file}"
 | 
					        [ -f "${temp_file}" ] && rm -f "${temp_file}"
 | 
				
			||||||
        tput cnorm 2>/dev/null
 | 
					        tput cnorm 2>/dev/null
 | 
				
			||||||
        echo -e "\n\033[1;44m 提示 \033[0m \033[31m操作已取消\033[0m\n"
 | 
					        echo -e "\n\033[1;44m 提示 \033[0m \033[31m操作已取消\033[0m\n"
 | 
				
			||||||
        exit 130
 | 
					        exit 130
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    # 创建临时文件
 | 
					 | 
				
			||||||
    function make_temp_file() {
 | 
					    function make_temp_file() {
 | 
				
			||||||
        local temp_dirs=("." "/tmp")
 | 
					        local temp_dirs=("." "/tmp")
 | 
				
			||||||
        local tmp_file=""
 | 
					        local tmp_file=""
 | 
				
			||||||
@@ -1605,65 +1596,49 @@ function animate_exec() {
 | 
				
			|||||||
        done
 | 
					        done
 | 
				
			||||||
        echo "${tmp_file}"
 | 
					        echo "${tmp_file}"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    # 更新显示
 | 
					 | 
				
			||||||
    function update_display() {
 | 
					    function update_display() {
 | 
				
			||||||
        local current_size=$(wc -c <"${temp_file}" 2>/dev/null || echo 0)
 | 
					        local current_size=$(wc -c <"${temp_file}" 2>/dev/null || echo 0)
 | 
				
			||||||
        # 如果文件大小没变,不更新
 | 
					 | 
				
			||||||
        if [[ $current_size -le $last_size ]]; then
 | 
					        if [[ $current_size -le $last_size ]]; then
 | 
				
			||||||
            return 1
 | 
					            return 1
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
        # 只在必要时读取文件
 | 
					 | 
				
			||||||
        local -a lines=()
 | 
					        local -a lines=()
 | 
				
			||||||
        mapfile -t -n "${max_lines}" lines < <(tail -n "$max_lines" "${temp_file}")
 | 
					        mapfile -t -n "${max_lines}" lines < <(tail -n "$max_lines" "${temp_file}")
 | 
				
			||||||
        # 处理每一行
 | 
					 | 
				
			||||||
        local -a processed_lines=()
 | 
					        local -a processed_lines=()
 | 
				
			||||||
        for ((i = 0; i < ${#lines[@]}; i++)); do
 | 
					        for ((i = 0; i < ${#lines[@]}; i++)); do
 | 
				
			||||||
            processed_lines[i]=$(simple_truncate "${lines[i]}")
 | 
					            processed_lines[i]=$(simple_truncate "${lines[i]}")
 | 
				
			||||||
        done
 | 
					        done
 | 
				
			||||||
        # 更新显示
 | 
					        tput cud1 2>/dev/null
 | 
				
			||||||
        tput cud1 2>/dev/null # 移动到标题下
 | 
					        echo -ne "\r\033[K"
 | 
				
			||||||
        echo -ne "\r\033[K"   # 清空当前行
 | 
					        tput cud1 2>/dev/null
 | 
				
			||||||
        tput cud1 2>/dev/null # 移动到内容区
 | 
					 | 
				
			||||||
        # 显示处理后的行
 | 
					 | 
				
			||||||
        for ((i = 0; i < $max_lines; i++)); do
 | 
					        for ((i = 0; i < $max_lines; i++)); do
 | 
				
			||||||
            echo -ne "\r\033[K" # 清空当前行
 | 
					            echo -ne "\r\033[K"
 | 
				
			||||||
            [[ $i -lt ${#processed_lines[@]} ]] && echo -ne "\033[2m${processed_lines[$i]}\033[0m"
 | 
					            [[ $i -lt ${#processed_lines[@]} ]] && echo -ne "\033[2m${processed_lines[$i]}\033[0m"
 | 
				
			||||||
            [[ $i -lt $((max_lines - 1)) ]] && tput cud1 2>/dev/null
 | 
					            [[ $i -lt $((max_lines - 1)) ]] && tput cud1 2>/dev/null
 | 
				
			||||||
        done
 | 
					        done
 | 
				
			||||||
        # 返回到标题行
 | 
					 | 
				
			||||||
        for ((i = 0; i < $max_lines + 1; i++)); do
 | 
					        for ((i = 0; i < $max_lines + 1; i++)); do
 | 
				
			||||||
            tput cuu1 2>/dev/null
 | 
					            tput cuu1 2>/dev/null
 | 
				
			||||||
        done
 | 
					        done
 | 
				
			||||||
        # 更新文件大小记录
 | 
					 | 
				
			||||||
        last_size=$current_size
 | 
					        last_size=$current_size
 | 
				
			||||||
        return 0
 | 
					        return 0
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    # 初始化
 | 
					 | 
				
			||||||
    local spinner_frames=(${spinners[$spinner_style]})
 | 
					    local spinner_frames=(${spinners[$spinner_style]})
 | 
				
			||||||
    local temp_file="$(make_temp_file)"
 | 
					    local temp_file="$(make_temp_file)"
 | 
				
			||||||
    trap "cleanup" INT TERM
 | 
					    trap "cleanup" INT TERM
 | 
				
			||||||
    tput civis 2>/dev/null # 隐藏光标
 | 
					    tput civis 2>/dev/null
 | 
				
			||||||
    # 预留显示空间
 | 
					    echo ''
 | 
				
			||||||
    echo '' # 标题行
 | 
					    echo ''
 | 
				
			||||||
    echo '' # 空行
 | 
					 | 
				
			||||||
    for ((i = 0; i < $max_lines; i++)); do
 | 
					    for ((i = 0; i < $max_lines; i++)); do
 | 
				
			||||||
        echo ''
 | 
					        echo ''
 | 
				
			||||||
    done
 | 
					    done
 | 
				
			||||||
    # 执行命令
 | 
					 | 
				
			||||||
    eval "${cmd}" >"${temp_file}" 2>&1 &
 | 
					    eval "${cmd}" >"${temp_file}" 2>&1 &
 | 
				
			||||||
    local cmd_pid=$!
 | 
					    local cmd_pid=$!
 | 
				
			||||||
    local last_size=0
 | 
					    local last_size=0
 | 
				
			||||||
    local spin_idx=0
 | 
					    local spin_idx=0
 | 
				
			||||||
    # 返回到标题行
 | 
					 | 
				
			||||||
    tput cuu $((max_lines + 2)) 2>/dev/null
 | 
					    tput cuu $((max_lines + 2)) 2>/dev/null
 | 
				
			||||||
    # 添加延迟允许命令开始执行
 | 
					 | 
				
			||||||
    sleep 0.05
 | 
					    sleep 0.05
 | 
				
			||||||
    # 显示初始状态
 | 
					 | 
				
			||||||
    echo -ne "\r\033[K◉ ${title} [\033[1m\033[34m${spinner_frames[$spin_idx]}\033[0m]"
 | 
					    echo -ne "\r\033[K◉ ${title} [\033[1m\033[34m${spinner_frames[$spin_idx]}\033[0m]"
 | 
				
			||||||
    spin_idx=$(((spin_idx + 1) % ${#spinner_frames[@]}))
 | 
					    spin_idx=$(((spin_idx + 1) % ${#spinner_frames[@]}))
 | 
				
			||||||
    # 检查初始输出
 | 
					 | 
				
			||||||
    update_display
 | 
					    update_display
 | 
				
			||||||
    # 监控命令执行 - 增加自适应刷新
 | 
					 | 
				
			||||||
    local update_count=0
 | 
					    local update_count=0
 | 
				
			||||||
    local adaptive_rate=$refresh_rate
 | 
					    local adaptive_rate=$refresh_rate
 | 
				
			||||||
    while kill -0 $cmd_pid 2>/dev/null; do
 | 
					    while kill -0 $cmd_pid 2>/dev/null; do
 | 
				
			||||||
@@ -1671,7 +1646,6 @@ function animate_exec() {
 | 
				
			|||||||
        spin_idx=$(((spin_idx + 1) % ${#spinner_frames[@]}))
 | 
					        spin_idx=$(((spin_idx + 1) % ${#spinner_frames[@]}))
 | 
				
			||||||
        if update_display; then
 | 
					        if update_display; then
 | 
				
			||||||
            update_count=$((update_count + 1))
 | 
					            update_count=$((update_count + 1))
 | 
				
			||||||
            # 连续更新太频繁则调整刷新率
 | 
					 | 
				
			||||||
            if [[ $update_count -gt 5 ]]; then
 | 
					            if [[ $update_count -gt 5 ]]; then
 | 
				
			||||||
                adaptive_rate=$(awk "BEGIN {print $adaptive_rate * 1.5; exit}")
 | 
					                adaptive_rate=$(awk "BEGIN {print $adaptive_rate * 1.5; exit}")
 | 
				
			||||||
                [[ $(awk "BEGIN {print ($adaptive_rate > 0.5); exit}") -eq 1 ]] && adaptive_rate=0.5
 | 
					                [[ $(awk "BEGIN {print ($adaptive_rate > 0.5); exit}") -eq 1 ]] && adaptive_rate=0.5
 | 
				
			||||||
@@ -1685,17 +1659,13 @@ function animate_exec() {
 | 
				
			|||||||
    done
 | 
					    done
 | 
				
			||||||
    wait $cmd_pid
 | 
					    wait $cmd_pid
 | 
				
			||||||
    local exit_status=$?
 | 
					    local exit_status=$?
 | 
				
			||||||
    # 最后一次更新显示
 | 
					 | 
				
			||||||
    update_display
 | 
					    update_display
 | 
				
			||||||
    # 显示完成状态
 | 
					 | 
				
			||||||
    if [ $exit_status -eq 0 ]; then
 | 
					    if [ $exit_status -eq 0 ]; then
 | 
				
			||||||
        echo -ne "\r\033[K◉ ${title} [\033[1m\033[32m✓\033[0m]\n"
 | 
					        echo -ne "\r\033[K◉ ${title} [\033[1m\033[32m✓\033[0m]\n"
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        echo -ne "\r\033[K◉ ${title} [\033[1m\033[31m✗\033[0m]\n"
 | 
					        echo -ne "\r\033[K◉ ${title} [\033[1m\033[31m✗\033[0m]\n"
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
    # 空行
 | 
					 | 
				
			||||||
    echo -ne "\r\033[K\n"
 | 
					    echo -ne "\r\033[K\n"
 | 
				
			||||||
    # 显示最终输出
 | 
					 | 
				
			||||||
    local actual_lines=$(wc -l <"${temp_file}" 2>/dev/null || echo 0)
 | 
					    local actual_lines=$(wc -l <"${temp_file}" 2>/dev/null || echo 0)
 | 
				
			||||||
    [[ $actual_lines -gt $max_lines ]] && actual_lines=$max_lines
 | 
					    [[ $actual_lines -gt $max_lines ]] && actual_lines=$max_lines
 | 
				
			||||||
    if [[ $actual_lines -gt 0 ]]; then
 | 
					    if [[ $actual_lines -gt 0 ]]; then
 | 
				
			||||||
@@ -1707,7 +1677,6 @@ function animate_exec() {
 | 
				
			|||||||
            echo -ne "\r\033[K\033[2m${line}\033[0m\n"
 | 
					            echo -ne "\r\033[K\033[2m${line}\033[0m\n"
 | 
				
			||||||
        done
 | 
					        done
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
    # 清理并返回
 | 
					 | 
				
			||||||
    tput cnorm 2>/dev/null
 | 
					    tput cnorm 2>/dev/null
 | 
				
			||||||
    rm -f "${temp_file}"
 | 
					    rm -f "${temp_file}"
 | 
				
			||||||
    return $exit_status
 | 
					    return $exit_status
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user