Files
dock/xu
2026-02-27 15:52:12 +08:00

361 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 全能安装脚本 (咸V咆哮制作)
# 更新1. 提取全局域名与版本变量,方便后续维护
# 2. 动态拼接架构下载链接,适配新版 release
# 3. 数据库机制更新1.db(客户标准) / 2.db(私人)
# 4. 增加数据库防呆校验,防止下载错误网页死循环
# 5. 新增:私人模式(模式2)密码防护机制
# ==========================================
# --- 颜色配置 ---
Red="\033[31m"
Green="\033[32m"
Yellow="\033[33m"
Blue="\033[36m"
Font="\033[0m"
# --- 核心配置 (用户定制) ---
# 定义基础域名和安装包版本号
BASE_DOMAIN="git.77582585.xyz"
REPO_PATH="3344/dock/releases/download"
XUI_VERSION="x-uiv2.8.10"
# 定义数据库专属 Release 版本号
DB_RELEASE="3xui1"
# 数据库链接 (使用变量自动拼接)
DB_URL_PUBLIC="https://${BASE_DOMAIN}/${REPO_PATH}/${DB_RELEASE}/1.db" # 模式1链接 (客户使用)
DB_URL_PRIVATE="https://${BASE_DOMAIN}/${REPO_PATH}/${DB_RELEASE}/2.db" # 模式2链接 (私人使用)
# --- 安全配置 ---
# 设置私人模式的专属安装密码 (你可以随时在这里修改)
PRIVATE_AUTH_CODE="3344521"
# 默认账号设置 (数据库下载后会被强制重置为此账号,防止无法登录)
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"
# ==========================================
# 1. 模式选择与安全验证
# ==========================================
clear
echo -e "${Blue}#################################################${Font}"
echo -e "${Blue}# X-UI 自动安装脚本 (咸V咆哮制作1.4) #${Font}"
echo -e "${Blue}#################################################${Font}"
echo -e "${Yellow}请选择安装配置模式:${Font}"
echo -e "-------------------------------------------------"
echo -e "1. ${Green}标准配置安装${Font} (使用 1.db 客户数据库)"
echo -e "2. ${Red}私人配置安装${Font} (使用 2.db 私人数据库,需授权码)"
echo -e "-------------------------------------------------"
read -p "请输入数字 [1-2] (默认1): " INSTALL_MODE
[[ -z "$INSTALL_MODE" ]] && INSTALL_MODE="1"
# 密码验证逻辑
if [ "$INSTALL_MODE" == "2" ]; then
echo -e "-------------------------------------------------"
# -s 参数用于隐藏用户输入的密码
read -s -p "请输入私人配置专属授权码: " INPUT_PWD
echo "" # 换行输出
if [ "$INPUT_PWD" != "$PRIVATE_AUTH_CODE" ]; then
echo -e "${Red}!! 授权码错误:拒绝访问私人配置,脚本已终止 !!${Font}"
exit 1
else
echo -e "${Green}>> 授权通过,准备安装私人配置...${Font}"
fi
echo -e "-------------------------------------------------"
fi
# ==========================================
# 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
if (( $(echo "$SPEED_GLOBAL == 999" | bc -l) )); then
echo -e "${Green}>> 判定为中国大陆环境 (无法连接Google),自动选择阿里云源${Font}"
SOURCE_CHOICE="1"
elif (( $(echo "$SPEED_CN < $SPEED_GLOBAL" | bc -l) )); then
echo -e "${Green}>> 阿里云响应更快,自动选择阿里云源${Font}"
SOURCE_CHOICE="1"
else
echo -e "${Green}>> 国际网络良好,自动选择 Cloudflare/官方源${Font}"
SOURCE_CHOICE="2"
fi
}
if command -v bc >/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. 系统环境处理 (双核下载引擎安装)
# ==========================================
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" || echo -e "${Red}源更新超时,尝试继续...${Font}"
apt-get install -y curl wget tar ca-certificates bc
install_soft sqlite3
install_soft axel
install_soft aria2
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 bc >/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
DOWNLOAD_URL="https://${BASE_DOMAIN}/${REPO_PATH}/${XUI_VERSION}/${FILE_NAME}"
echo -e "${Green}检测到架构: $ARCH${Font}"
echo -e "${Green}安装包直链: $DOWNLOAD_URL${Font}"
# ==========================================
# 6. 智能下载管理器
# ==========================================
download_manager() {
local url=$1
local file=$2
rm -f "$file"
if command -v axel >/dev/null 2>&1; then
if axel -n 16 -k -q -o "$file" "$url"; then return 0; fi
fi
if command -v aria2c >/dev/null 2>&1; then
if aria2c -x 16 -s 16 -k 1M -o "$file" "$url" >/dev/null 2>&1; then return 0; fi
fi
if wget $NET_OPT --no-check-certificate --timeout=30 --tries=3 -O "$file" "$url"; then return 0; fi
curl $NET_OPT -L -k --connect-timeout 30 --retry 3 -o "$file" "$url"
}
echo -e "${Yellow}>> [5/7] 下载安装包...${Font}"
cd /usr/local/
download_manager "$DOWNLOAD_URL" "$FILE_NAME"
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
echo -e "${Yellow}>> 正在下载 1.db (客户标准配置)...${Font}"
TARGET_DB="$DB_URL_PUBLIC"
else
echo -e "${Yellow}>> 正在下载 2.db (私人配置)...${Font}"
TARGET_DB="$DB_URL_PRIVATE"
fi
download_manager "$TARGET_DB" "$DB_PATH"
# --- 防报错网页校验 ---
if [ ! -s "$DB_PATH" ] || [ $(stat -c%s "$DB_PATH") -lt 10240 ]; then
echo -e "${Red}警告:数据库下载失败或文件异常(大小不足 10KB),已自动回退为空白数据库!${Font}"
cp /usr/local/x-ui/bin/x-ui.db "$DB_PATH"
else
echo -e "${Green}数据库配置下载且校验成功!${Font}"
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;"
CURRENT_PASS=$(sqlite3 "$DB_PATH" "SELECT password FROM users WHERE id=1;")
if [ "$CURRENT_PASS" == "$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 安装完成 (咸V咆哮制作) ${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 "当前模式 ${Yellow}$([ "$INSTALL_MODE" == "1" ] && echo "客户配置(1.db)" || echo "私人配置(2.db)")${Font}"
echo -e "${Blue}#################################################${Font}"