Files
dock/xu1
2026-03-02 16:07:45 +08:00

338 lines
13 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# ==========================================
# 标题X-UI 全能安装脚本 (全面中文化定制版)
# 更新1. 增加 30 秒强制超时与进度条显示
# 2. 增加备用下载节点自动回退机制
# 3. 修复 bc 依赖报错,改为底层 awk 运算
# ==========================================
# --- 颜色配置 ---
Red="\033[31m"
Green="\033[32m"
Yellow="\033[33m"
Blue="\033[36m"
Font="\033[0m"
# --- 核心配置 (用户定制) ---
DB_URL_PUBLIC="https://git.77582585.xyz/3344/dock/releases/download/3xui/x-ui%20%E6%88%B702.db"
DB_URL_PRIVATE="https://git.77582585.xyz/attachments/c457401f-76dd-4499-8ea3-a8b628bc963a"
INSTALL_PATH="/usr/local/x-ui"
BIN_LINK="/usr/bin/x-ui"
DB_PATH="/etc/x-ui/x-ui.db"
SET_USER="3344"
SET_PASS="3344"
SET_PORT="8443"
BASE_URL="https://git.77582585.xyz/3344/dock/releases/download/x-uiv2.8.10"
# ==========================================
# 1. 模式选择
# ==========================================
clear
echo -e "${Blue}#################################################${Font}"
echo -e "${Blue}# X-UI 自动安装脚本 (定制中文优化版) #${Font}"
echo -e "${Blue}#################################################${Font}"
echo -e "${Yellow}请选择安装配置模式:${Font}"
echo -e "1. ${Green}标准配置安装${Font} (使用指定的公共数据库配置)"
echo -e "2. ${Green}私人配置安装${Font} (使用私人数据库配置)"
echo -e "-------------------------------------------------"
read -p "请输入数字 [1-2] (默认: 1): " INSTALL_MODE
[[ -z "$INSTALL_MODE" ]] && INSTALL_MODE="1"
# ==========================================
# 2. 网络环境智能检测
# ==========================================
check_network() {
echo -e "${Yellow}>> [0/7] 正在检测网络环境...${Font}"
HAS_IPV4=0
HAS_IPV6=0
if curl -s4m2 https://www.google.com/generate_204 >/dev/null 2>&1 || curl -s4m2 https://www.baidu.com >/dev/null 2>&1; then
HAS_IPV4=1
fi
if curl -s6m2 https://www.google.com/generate_204 >/dev/null 2>&1; then
HAS_IPV6=1
fi
if [[ $HAS_IPV4 -eq 1 ]]; then
echo -e "${Green}检测到 IPv4 网络,将优先使用 IPv4 通道${Font}"
NET_OPT="-4"
elif [[ $HAS_IPV6 -eq 1 ]]; then
echo -e "${Green}检测到纯 IPv6 网络,将自动切换至 IPv6 通道${Font}"
NET_OPT="-6"
else
echo -e "${Red}错误:未检测到任何可用网络连接!${Font}"
exit 1
fi
}
check_network
# ==========================================
# 3. 智能源选择 (自动测速版)
# ==========================================
auto_select_source() {
echo -e "${Yellow}>> [1/7] 正在智能测速并选择最佳软件源...${Font}"
ALIYUN_URL="https://mirrors.aliyun.com"
GOOGLE_URL="https://www.google.com"
echo -n " 测试国际网络连通性... "
SPEED_GLOBAL=$(curl -o /dev/null -s -w '%{time_total}' --connect-timeout 2 "$GOOGLE_URL")
if [ $? -ne 0 ]; then SPEED_GLOBAL=999; echo "超时或无法连接"; else echo "${SPEED_GLOBAL}"; fi
echo -n " 测试国内网络连通性... "
SPEED_CN=$(curl -o /dev/null -s -w '%{time_total}' --connect-timeout 2 "$ALIYUN_URL")
if [ $? -ne 0 ]; then SPEED_CN=999; echo "超时或无法连接"; else echo "${SPEED_CN}"; fi
# 使用 awk 代替 bc 避免报错
if [ "$(awk -v sg="$SPEED_GLOBAL" 'BEGIN {print (sg == 999) ? "1" : "0"}')" == "1" ]; then
echo -e "${Green}>> 判定为中国大陆网络环境,自动选择阿里云软件源${Font}"
SOURCE_CHOICE="1"
elif [ "$(awk -v sc="$SPEED_CN" -v sg="$SPEED_GLOBAL" 'BEGIN {print (sc < sg) ? "1" : "0"}')" == "1" ]; then
echo -e "${Green}>> 阿里云响应速度更快,自动选择阿里云软件源${Font}"
SOURCE_CHOICE="1"
else
echo -e "${Green}>> 国际网络状况良好,自动选择 Cloudflare/官方源${Font}"
SOURCE_CHOICE="2"
fi
}
if command -v awk >/dev/null 2>&1 && command -v curl >/dev/null 2>&1; then
auto_select_source
else
echo -e "${Yellow}系统缺失测速组件,默认选择官方软件源...${Font}"
SOURCE_CHOICE="2"
fi
PM="apt"
if [[ -f /etc/redhat-release ]] || command -v yum >/dev/null 2>&1; then PM="yum"; fi
if [ "$SOURCE_CHOICE" != "3" ]; then
echo -e "${Yellow}>> 正在优化系统软件源配置...${Font}"
if [ "$PM" == "apt" ]; then
if [ -f /etc/os-release ]; then . /etc/os-release; CODENAME=$VERSION_CODENAME; else CODENAME="bookworm"; fi
cp /etc/apt/sources.list /etc/apt/sources.list.bak.$(date +%s)
if [ "$SOURCE_CHOICE" == "1" ]; then DOMAIN="mirrors.aliyun.com"; else DOMAIN="debian.cloudflare.mirrors.com"; fi
cat > /etc/apt/sources.list <<EOF
deb https://$DOMAIN/debian/ $CODENAME main non-free non-free-firmware contrib
deb-src https://$DOMAIN/debian/ $CODENAME main non-free non-free-firmware contrib
deb https://$DOMAIN/debian-security/ $CODENAME-security main
deb https://$DOMAIN/debian/ $CODENAME-updates main non-free non-free-firmware contrib
EOF
elif [ "$PM" == "yum" ]; then
mkdir -p /etc/yum.repos.d/bak
mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/bak/ 2>/dev/null
if [ "$SOURCE_CHOICE" == "1" ]; then
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
else
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.edge.kernel.org/centos/7/os/x86_64/
fi
timeout 60 yum makecache >/dev/null 2>&1
fi
fi
# ==========================================
# 4. 系统环境处理 (去除 bc)
# ==========================================
echo -e "${Yellow}>> [2/7] 正在安装系统依赖与下载引擎...${Font}"
install_soft() {
if [ "$PM" == "apt" ]; then apt-get install -y $1 >/dev/null 2>&1; elif [ "$PM" == "yum" ]; then yum install -y $1 >/dev/null 2>&1; fi
}
if [ "$PM" == "apt" ]; then
pgrep -x "apt" && killall apt apt-get dpkg >/dev/null 2>&1
rm -rf /var/lib/apt/lists/lock /var/lib/dpkg/lock*
dpkg --configure -a >/dev/null 2>&1
apt-get update -o Acquire::http::Timeout="20" >/dev/null 2>&1
apt-get install -y curl wget tar ca-certificates
install_soft sqlite3
echo -n " 安装 Axel 多线程加速器... "
install_soft axel && echo "完成" || echo "失败 (将跳过)"
echo -n " 安装 Aria2 多线程加速器... "
install_soft aria2 && echo "完成" || echo "失败 (将跳过)"
if ! apt-get install -y ntpdate >/dev/null 2>&1; then apt-get install -y ntpsec-ntpdate >/dev/null 2>&1; fi
else
yum install -y epel-release >/dev/null 2>&1
yum install -y curl wget tar >/dev/null 2>&1
install_soft sqlite3
install_soft ntpdate
install_soft axel
install_soft aria2
fi
# ==========================================
# 5. 时间与架构匹配
# ==========================================
echo -e "${Yellow}>> [3/7] 正在校准系统时间...${Font}"
rm -f /etc/localtime
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
if command -v ntpdate >/dev/null 2>&1; then
ntpdate pool.ntp.org >/dev/null 2>&1
else
date -s "$(curl -sI g.cn | grep Date | cut -d' ' -f3-6)Z" >/dev/null 2>&1
fi
echo -e "${Yellow}>> [4/7] 正在识别系统架构并匹配下载源...${Font}"
ARCH=$(uname -m)
FILE_NAME=""
case $ARCH in
x86_64) FILE_NAME="x-ui-linux-amd64.tar.gz" ;;
aarch64|armv8) FILE_NAME="x-ui-linux-arm64.tar.gz" ;;
i386|i686) FILE_NAME="x-ui-linux-386.tar.gz" ;;
armv5*) FILE_NAME="x-ui-linux-armv5.tar.gz" ;;
armv6*) FILE_NAME="x-ui-linux-armv6.tar.gz" ;;
armv7*) FILE_NAME="x-ui-linux-armv7.tar.gz" ;;
s390x) FILE_NAME="x-ui-linux-s390x.tar.gz" ;;
*) echo -e "${Red}不支持当前的系统架构: $ARCH${Font}"; exit 1 ;;
esac
echo -e "${Green}成功检测到系统架构: $ARCH${Font}"
# 动态生成备用链接库
DOWNLOAD_URL_1="${BASE_URL}/${FILE_NAME}"
# 备用加速节点(不需要科学上网)
DOWNLOAD_URL_2="https://ghproxy.net/https://github.com/vaxilu/x-ui/releases/download/v2.8.10/${FILE_NAME}"
DOWNLOAD_URL_3="https://github.moeyy.xyz/https://github.com/vaxilu/x-ui/releases/download/v2.8.10/${FILE_NAME}"
# ==========================================
# 6. 智能下载管理器 (30秒超时机制 + 备用链接轮询)
# ==========================================
download_manager() {
local file=$1
shift
local urls=("$@")
for url in "${urls[@]}"; do
echo -e "\n${Yellow}>> 正在尝试拉取链接: ${url}${Font}"
rm -f "$file"
# 优先级 1: Axel (去掉 -q 显示进度条,增加 30s 超时)
if command -v axel >/dev/null 2>&1; then
echo -e "${Green}>> [策略1] 启用 Axel 引擎 (限制30秒)...${Font}"
if timeout 30 axel -n 16 -k -o "$file" "$url"; then return 0; fi
echo -e "${Red}Axel 超时或失败,切换下一个引擎...${Font}"
fi
# 优先级 2: Aria2 (增加 30s 超时)
if command -v aria2c >/dev/null 2>&1; then
echo -e "${Green}>> [策略2] 启用 Aria2 引擎 (限制30秒)...${Font}"
if timeout 30 aria2c -x 16 -s 16 -k 1M -o "$file" "$url"; then return 0; fi
echo -e "${Red}Aria2 超时或失败,切换下一个引擎...${Font}"
fi
# 优先级 3: Wget (自带 30s 超时)
echo -e "${Yellow}>> [策略3] 启用 Wget 单线程下载 (限制30秒)...${Font}"
if wget $NET_OPT --no-check-certificate --timeout=30 --tries=1 -O "$file" "$url"; then return 0; fi
# 优先级 4: Curl (最大时间 30s)
echo -e "${Yellow}>> [策略4] 启用 Curl 保底下载 (限制30秒)...${Font}"
if curl $NET_OPT -L -k --connect-timeout 10 --max-time 30 --retry 1 -o "$file" "$url"; then return 0; fi
echo -e "${Red}>> 当前链接下载失败,正在切换备用节点...${Font}"
done
return 1 # 所有链接全部失败
}
echo -e "${Yellow}>> [5/7] 开始下载 X-UI 安装包 (网络模式: $NET_OPT)...${Font}"
cd /usr/local/
# 传入文件名和三个备用链接
if ! download_manager "$FILE_NAME" "$DOWNLOAD_URL_1" "$DOWNLOAD_URL_2" "$DOWNLOAD_URL_3"; then
echo -e "${Red}严重错误:主链接及所有备用节点下载均失败,请检查服务器网络!${Font}"
exit 1
fi
if ! tar -tzf "$FILE_NAME" >/dev/null 2>&1; then
echo -e "${Red}严重错误:安装包已损坏!${Font}"
exit 1
fi
# ==========================================
# 7. 安装与配置
# ==========================================
echo -e "${Yellow}>> [6/7] 正在执行安装与配置流程...${Font}"
systemctl stop x-ui >/dev/null 2>&1
killall x-ui >/dev/null 2>&1
rm -rf x-ui
tar zxvf "$FILE_NAME" >/dev/null
cd x-ui
chmod +x x-ui x-ui.sh bin/xray-linux-*
ln -sf "$INSTALL_PATH/x-ui.sh" "$BIN_LINK"
mkdir -p /etc/x-ui/
rm -f "$DB_PATH"
if [ "$INSTALL_MODE" == "1" ]; then
TARGET_DB="$DB_URL_PUBLIC"
else
TARGET_DB="$DB_URL_PRIVATE"
fi
echo -e "${Yellow}>> 正在下载数据库配置...${Font}"
download_manager "$DB_PATH" "$TARGET_DB"
if [ ! -s "$DB_PATH" ] || [ $(stat -c%s "$DB_PATH") -lt 1000 ]; then
echo -e "${Red}警告:数据库下载失败,使用空数据库进行初始化...${Font}"
cp /usr/local/x-ui/bin/x-ui.db "$DB_PATH"
fi
echo -e "${Yellow}>> 正在强制重置管理员账户及端口权限...${Font}"
chmod 777 "$DB_PATH" >/dev/null 2>&1
RESET_SUCCESS=0
if command -v sqlite3 >/dev/null 2>&1; then
sqlite3 -cmd ".timeout 2000" "$DB_PATH" "UPDATE settings SET value='/' WHERE key='webBasePath';"
sqlite3 -cmd ".timeout 2000" "$DB_PATH" "UPDATE settings SET value='$SET_PORT' WHERE key='webPort';"
sqlite3 -cmd ".timeout 2000" "$DB_PATH" "UPDATE users SET username='$SET_USER', password='$SET_PASS' WHERE id=1;"
if [ "$(sqlite3 "$DB_PATH" "SELECT password FROM users WHERE id=1;")" == "$SET_PASS" ]; then RESET_SUCCESS=1; fi
fi
if [ $RESET_SUCCESS -eq 0 ]; then
./x-ui setting -username "$SET_USER" -password "$SET_PASS" -port "$SET_PORT" >/dev/null 2>&1
fi
chmod 644 "$DB_PATH" >/dev/null 2>&1
# ==========================================
# 8. 启动与放行
# ==========================================
echo -e "${Yellow}>> [7/7] 正在启动服务并配置防火墙...${Font}"
cat > /etc/systemd/system/x-ui.service <<EOF
[Unit]
Description=x-ui Service
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=$INSTALL_PATH
ExecStart=$INSTALL_PATH/x-ui
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable x-ui
systemctl restart x-ui
sleep 2
if command -v ufw >/dev/null 2>&1; then ufw allow $SET_PORT/tcp >/dev/null 2>&1; fi
if command -v firewall-cmd >/dev/null 2>&1; then
firewall-cmd --zone=public --add-port=$SET_PORT/tcp --permanent >/dev/null 2>&1
firewall-cmd --reload >/dev/null 2>&1
fi
iptables -I INPUT -p tcp --dport $SET_PORT -j ACCEPT 2>/dev/null
IP=$(curl -s4m5 ip.sb)
[ -z "$IP" ] && IP=$(curl -s6m5 ip.sb)
echo -e "\n${Blue}#################################################${Font}"
echo -e "${Green} X-UI 自动安装已全部完成 ${Font}"
echo -e "${Blue}#################################################${Font}"
echo -e "访问控制面板 ${Green}http://$IP:$SET_PORT${Font}"
echo -e "登录用户名 ${Green}$SET_USER${Font}"
echo -e "登录密码 ${Green}$SET_PASS${Font}"
echo -e "${Blue}#################################################${Font}"