32 Commits

Author SHA1 Message Date
efdf16b63b 添加 GoEdge-cdn 2026-02-12 21:38:52 +08:00
6882977dce 添加 ssh程 2026-01-28 11:49:07 +08:00
6468c298da 更新 03 2026-01-25 14:21:07 +08:00
8b27e9ada7 更新 03 2026-01-25 14:13:23 +08:00
56c5f6a99f 更新 03 2026-01-25 11:02:56 +08:00
07d0219e91 更新 03 2026-01-25 10:56:57 +08:00
f40c881050 更新 03 2026-01-25 10:40:13 +08:00
8da168f68b 更新 03 2026-01-25 10:37:17 +08:00
028262d6ee 更新 03 2026-01-25 01:11:31 +08:00
0f84acf296 更新 03 2026-01-25 01:07:27 +08:00
dd37499c73 更新 SublinkX 2026-01-23 14:37:09 +08:00
a2281125b6 添加 istc 2026-01-22 22:42:22 +08:00
beb89430a6 更新 te消息转发 2026-01-22 21:08:16 +08:00
efbbd6314e 更新 Docker容器管理面板 2026-01-22 21:02:33 +08:00
a67d1e936e 添加 te消息转发 2026-01-22 20:56:39 +08:00
b2634a40fd 更新 03 2026-01-22 19:24:17 +08:00
eac69646e9 更新 ru2 2026-01-22 18:50:03 +08:00
3970a4ad0b 更新 ru2 2026-01-22 18:40:15 +08:00
79d95b2419 更新 ru2 2026-01-22 16:37:11 +08:00
52cff5e278 更新 ru2 2026-01-22 16:33:58 +08:00
e2ff06247c 添加 ru2 2026-01-22 16:29:43 +08:00
5f7756227d 添加 ru2进制下载安装 2026-01-22 16:22:53 +08:00
84e5674b80 更新 ru 2026-01-22 16:10:52 +08:00
0733b5bd4d 更新 cl穿透 2026-01-20 22:21:39 +08:00
48765d2bcb 添加 cl穿透 2026-01-20 22:20:33 +08:00
9ef336f741 更新 121 2026-01-20 22:17:29 +08:00
a4f0b8c761 更新 121 2026-01-20 22:13:55 +08:00
78839d62c0 添加 121 2026-01-20 22:10:58 +08:00
1aa2db6d7c 更新 dock安装cf 2026-01-20 09:44:17 +08:00
a459c44f9b 更新 xu 2026-01-20 09:31:07 +08:00
23652fd5bc 更新 xu 2026-01-20 09:28:12 +08:00
f064875e65 更新 xu 2026-01-19 23:16:22 +08:00
14 changed files with 1014 additions and 850 deletions

627
03
View File

@@ -1,484 +1,167 @@
#!/bin/bash
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# ================= 配置区域 =================
VERSION="1.1.15"
DATA_DIR="/var/lib/rustdesk-server"
BACKUP_DIR="/tmp/rustdesk_backup_$(date +%s)"
# ===========================================
# 显示标题
echo -e "${CYAN}"
echo "================================================"
echo " 全端口扫描诊断工具 v3.0"
echo "================================================"
echo -e "${NC}"
echo "========================================================"
echo " RustDesk Server 全能修复脚本 (安装/转移/修复/启动)"
echo "========================================================"
# 变量定义
SCAN_RESULTS=()
OPEN_PORTS=()
TOTAL_PORTS_SCANNED=0
START_TIME=0
END_TIME=0
# --- 1. 智能查找并备份/转移现有的密钥 ---
echo ">>> [1/7] 正在扫描并搜集现有的密钥文件..."
mkdir -p "$BACKUP_DIR"
# 函数:检查命令是否存在
check_command() {
if command -v "$1" &> /dev/null; then
return 0
else
return 1
# 定义查找函数
save_files() {
local src_dir=$1
if [ -f "${src_dir}/id_ed25519.pub" ]; then
echo " 发现密钥在: ${src_dir}"
cp "${src_dir}/id_ed25519" "$BACKUP_DIR/" 2>/dev/null
cp "${src_dir}/id_ed25519.pub" "$BACKUP_DIR/" 2>/dev/null
cp "${src_dir}/db_v2.sqlite3" "$BACKUP_DIR/" 2>/dev/null
# 标记为已找到
FOUND_KEYS=1
fi
}
# 函数:显示帮助信息
show_help() {
echo -e "${YELLOW}使用说明:${NC}"
echo "1. 本工具用于全面扫描目标的所有端口"
echo "2. 支持IP地址和域名测试"
echo "3. 提供多种扫描模式和速度选项"
echo "4. 生成详细的扫描报告"
echo ""
echo -e "${YELLOW}扫描模式:${NC}"
echo " - 快速扫描: 常用端口 (1-1000)"
echo " - 标准扫描: 常见服务端口 (1-10000)"
echo " - 全面扫描: 所有端口 (1-65535)"
echo " - 自定义扫描: 指定端口范围"
echo ""
}
# A. 检查官方目录 (是否有残留)
save_files "$DATA_DIR"
# B. 检查 Root 目录 (你刚才手动运行产生的地方)
save_files "/root"
# C. 检查当前目录
save_files "$(pwd)"
# 函数输入IP/域名
input_target() {
while true; do
echo -e "${BLUE}请输入要扫描的目标IP地址或域名${NC}"
read -p "目标地址: " TARGET
if [ -z "$TARGET" ]; then
echo -e "${RED}错误:目标地址不能为空!${NC}"
continue
fi
# 简单验证格式
if [[ "$TARGET" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] || [[ "$TARGET" =~ ^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
break
else
echo -e "${RED}错误请输入有效的IP地址或域名${NC}"
fi
done
}
# 函数:选择扫描模式
select_scan_mode() {
echo -e "${BLUE}请选择扫描模式:${NC}"
echo "1) 快速扫描 (1-1000端口)"
echo "2) 标准扫描 (1-10000端口)"
echo "3) 全面扫描 (1-65535端口)"
echo "4) 自定义端口范围"
echo "5) 常用服务端口扫描"
while true; do
read -p "请选择 [1-5]: " MODE
case $MODE in
1)
START_PORT=1
END_PORT=1000
MODE_NAME="快速扫描"
break
;;
2)
START_PORT=1
END_PORT=10000
MODE_NAME="标准扫描"
break
;;
3)
START_PORT=1
END_PORT=65535
MODE_NAME="全面扫描"
break
;;
4)
input_custom_range
MODE_NAME="自定义扫描"
break
;;
5)
scan_common_services
MODE_NAME="常用服务扫描"
break
;;
*)
echo -e "${RED}错误请输入1-5之间的数字${NC}"
;;
esac
done
}
# 函数:输入自定义端口范围
input_custom_range() {
while true; do
echo -e "${BLUE}请输入自定义端口范围:${NC}"
read -p "起始端口: " START_PORT
read -p "结束端口: " END_PORT
if [[ ! "$START_PORT" =~ ^[0-9]+$ ]] || [[ ! "$END_PORT" =~ ^[0-9]+$ ]]; then
echo -e "${RED}错误:端口必须是数字!${NC}"
continue
fi
if [ "$START_PORT" -lt 1 ] || [ "$END_PORT" -gt 65535 ]; then
echo -e "${RED}错误:端口范围必须在 1-65535 之间!${NC}"
continue
fi
if [ "$START_PORT" -gt "$END_PORT" ]; then
echo -e "${RED}错误:起始端口不能大于结束端口!${NC}"
continue
fi
break
done
}
# 函数:常用服务端口扫描
scan_common_services() {
# 常见服务端口列表
COMMON_PORTS=(21 22 23 25 53 80 110 111 135 139 143 443 445 993 995 1723 3306 3389 5432 5900 6379 27017 25565)
echo -e "${CYAN}开始扫描常用服务端口...${NC}"
echo -e "扫描端口: ${YELLOW}${COMMON_PORTS[*]}${NC}"
START_TIME=$(date +%s)
for port in "${COMMON_PORTS[@]}"; do
scan_single_port "$port"
done
END_TIME=$(date +%s)
return 0
}
# 函数:扫描单个端口
scan_single_port() {
local port=$1
local result=""
# 使用TCP连接测试
if timeout 1 bash -c "echo > /dev/tcp/$TARGET/$port" 2>/dev/null; then
result="${GREEN}开放${NC}"
OPEN_PORTS+=("$port")
# 尝试识别服务
local service=$(identify_service "$port")
result="$result - $service"
else
result="${RED}关闭${NC}"
fi
SCAN_RESULTS+=("端口 $port: $result")
TOTAL_PORTS_SCANNED=$((TOTAL_PORTS_SCANNED + 1))
# 显示实时进度
if [ $TOTAL_PORTS_SCANNED -eq 1 ] || [ $((TOTAL_PORTS_SCANNED % 100)) -eq 0 ] || [ $TOTAL_PORTS_SCANNED -le 50 ]; then
echo -e "扫描进度: $TOTAL_PORTS_SCANNED 端口 - 端口 $port: $result"
fi
}
# 函数:识别服务
identify_service() {
local port=$1
case $port in
21) echo "FTP" ;;
22) echo "SSH" ;;
23) echo "Telnet" ;;
25) echo "SMTP" ;;
53) echo "DNS" ;;
80) echo "HTTP" ;;
110) echo "POP3" ;;
111) echo "RPC" ;;
135) echo "RPC" ;;
139) echo "NetBIOS" ;;
143) echo "IMAP" ;;
443) echo "HTTPS" ;;
445) echo "SMB" ;;
993) echo "IMAPS" ;;
995) echo "POP3S" ;;
1723) echo "PPTP" ;;
3306) echo "MySQL" ;;
3389) echo "RDP" ;;
5432) echo "PostgreSQL" ;;
5900) echo "VNC" ;;
6379) echo "Redis" ;;
27017) echo "MongoDB" ;;
25565) echo "Minecraft" ;;
*) echo "未知服务" ;;
esac
}
# 函数:端口范围扫描
scan_port_range() {
local start=$1
local end=$2
echo -e "${CYAN}开始扫描端口范围: $start - $end${NC}"
echo -e "目标: ${YELLOW}$TARGET${NC}"
echo -e "预计端口数量: $((end - start + 1))"
echo ""
START_TIME=$(date +%s)
for ((port=start; port<=end; port++)); do
scan_single_port "$port"
done
END_TIME=$(date +%s)
}
# 函数:并行扫描(加速)
parallel_scan() {
local start=$1
local end=$2
local batch_size=1000
local max_parallel=50
echo -e "${CYAN}开始并行扫描端口范围: $start - $end${NC}"
echo -e "目标: ${YELLOW}$TARGET${NC}"
echo -e "并行度: $max_parallel"
echo ""
START_TIME=$(date +%s)
for ((batch_start=start; batch_start<=end; batch_start+=batch_size)); do
local batch_end=$((batch_start + batch_size - 1))
if [ $batch_end -gt $end ]; then
batch_end=$end
fi
echo -e "${YELLOW}扫描批次: $batch_start - $batch_end${NC}"
for ((port=batch_start; port<=batch_end; port++)); do
# 控制并行数量
(
if timeout 1 bash -c "echo > /dev/tcp/$TARGET/$port" 2>/dev/null; then
echo -e "${GREEN}发现开放端口: $port${NC} - $(identify_service $port)"
OPEN_PORTS+=("$port")
fi
) &
# 控制并发数
if [[ $(jobs -r -p | wc -l) -ge $max_parallel ]]; then
wait -n
fi
done
wait
TOTAL_PORTS_SCANNED=$((TOTAL_PORTS_SCANNED + batch_size))
echo -e "已完成: $TOTAL_PORTS_SCANNED/$((end - start + 1)) 端口"
done
END_TIME=$(date +%s)
}
# 函数Ping测试
ping_test() {
echo -e "\n${PURPLE}=== 网络连通性测试 ===${NC}"
echo -e "目标: ${YELLOW}$TARGET${NC}"
if ping -c 3 -W 2 "$TARGET" &> /dev/null; then
echo -e "${GREEN}✓ 网络连通正常${NC}"
return 0
else
echo -e "${RED}✗ 网络不通${NC}"
return 1
fi
}
# 函数DNS解析测试
dns_test() {
echo -e "\n${PURPLE}=== DNS 解析测试 ===${NC}"
if [[ "$TARGET" =~ ^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
echo -e "${CYAN}检测到域名进行DNS解析...${NC}"
if check_command nslookup; then
if nslookup "$TARGET" &> /dev/null; then
echo -e "${GREEN}✓ DNS 解析成功${NC}"
nslookup "$TARGET" | grep -A 5 "Name:"
else
echo -e "${RED}✗ DNS 解析失败${NC}"
fi
else
echo -e "${YELLOW}⚠ DNS 查询工具未安装${NC}"
fi
else
echo -e "${CYAN}检测到IP地址跳过DNS解析${NC}"
fi
}
# 函数:生成扫描报告
generate_scan_report() {
local duration=$((END_TIME - START_TIME))
echo -e "\n${PURPLE}=== 扫描报告 ===${NC}"
echo -e "扫描时间: $(date)"
echo -e "目标地址: ${YELLOW}$TARGET${NC}"
echo -e "扫描模式: ${YELLOW}$MODE_NAME${NC}"
if [ "$MODE_NAME" != "常用服务扫描" ]; then
echo -e "端口范围: ${YELLOW}$START_PORT - $END_PORT${NC}"
fi
echo -e "扫描时长: ${YELLOW}${duration} 秒${NC}"
echo -e "扫描端口总数: ${YELLOW}$TOTAL_PORTS_SCANNED${NC}"
echo -e "开放端口数量: ${YELLOW}${#OPEN_PORTS[@]}${NC}"
if [ ${#OPEN_PORTS[@]} -gt 0 ]; then
echo -e "\n${GREEN}=== 开放的端口 ===${NC}"
printf "端口\t状态\t服务\n"
printf "====\t====\t====\n"
# 对端口进行排序
IFS=$'\n' sorted_ports=($(sort -n <<<"${OPEN_PORTS[*]}"))
unset IFS
for port in "${sorted_ports[@]}"; do
local service=$(identify_service "$port")
printf "%-6d\t${GREEN}%-6s${NC}\t%-15s\n" "$port" "开放" "$service"
done
# 显示端口统计
echo -e "\n${CYAN}端口统计:${NC}"
echo -e "标准服务端口 (1-1024): $(echo "${OPEN_PORTS[@]}" | tr ' ' '\n' | awk '$1 <= 1024' | wc -l)"
echo -e "注册端口 (1025-49151): $(echo "${OPEN_PORTS[@]}" | tr ' ' '\n' | awk '$1 > 1024 && $1 <= 49151' | wc -l)"
echo -e "动态端口 (49152-65535): $(echo "${OPEN_PORTS[@]}" | tr ' ' '\n' | awk '$1 > 49151' | wc -l)"
else
echo -e "\n${RED}未发现任何开放端口${NC}"
fi
# 安全建议
echo -e "\n${YELLOW}=== 安全建议 ===${NC}"
if [ ${#OPEN_PORTS[@]} -eq 0 ]; then
echo -e "${GREEN}● 所有扫描端口均关闭,安全性良好${NC}"
elif [ ${#OPEN_PORTS[@]} -le 5 ]; then
echo -e "${YELLOW}● 开放端口数量较少,建议检查服务配置${NC}"
else
echo -e "${RED}● 开放端口较多,建议进行安全审计${NC}"
fi
}
# 函数:选择扫描速度
select_scan_speed() {
echo -e "${BLUE}请选择扫描速度:${NC}"
echo "1) 慢速扫描 (准确率高)"
echo "2) 中速扫描 (平衡模式)"
echo "3) 快速扫描 (可能漏扫)"
echo "4) 并行扫描 (最快速度)"
while true; do
read -p "请选择 [1-4]: " SPEED
case $SPEED in
1)
TIMEOUT=2
SPEED_NAME="慢速扫描"
break
;;
2)
TIMEOUT=1
SPEED_NAME="中速扫描"
break
;;
3)
TIMEOUT=0.5
SPEED_NAME="快速扫描"
break
;;
4)
TIMEOUT=1
SPEED_NAME="并行扫描"
break
;;
*)
echo -e "${RED}错误请输入1-4之间的数字${NC}"
;;
esac
done
}
# 主函数
main() {
# 显示帮助信息
show_help
# 获取用户输入
input_target
# 网络基础测试
dns_test
if ! ping_test; then
echo -e "${YELLOW}网络不通,是否继续扫描?(y/n)${NC}"
read -p "选择: " CONTINUE
if [[ "$CONTINUE" != "y" && "$CONTINUE" != "Y" ]]; then
echo -e "${RED}扫描终止${NC}"
exit 1
fi
fi
# 选择扫描模式和速度
select_scan_mode
select_scan_speed
echo -e "\n${GREEN}开始端口扫描...${NC}"
echo -e "目标: ${YELLOW}$TARGET${NC}"
echo -e "模式: ${YELLOW}$MODE_NAME${NC}"
echo -e "速度: ${YELLOW}$SPEED_NAME${NC}"
# 执行扫描
case $MODE in
5)
# 常用服务扫描已在 select_scan_mode 中处理
;;
*)
if [ "$SPEED_NAME" = "并行扫描" ]; then
parallel_scan "$START_PORT" "$END_PORT"
else
scan_port_range "$START_PORT" "$END_PORT"
fi
;;
esac
# 生成报告
generate_scan_report
echo -e "\n${GREEN}端口扫描完成!${NC}"
}
# 检查系统要求
check_requirements() {
local missing=()
for cmd in ping timeout; do
if ! command -v "$cmd" &> /dev/null; then
missing+=("$cmd")
fi
done
if [ ${#missing[@]} -gt 0 ]; then
echo -e "${RED}错误: 缺少必要的命令: ${missing[*]}${NC}"
echo -e "${YELLOW}请安装缺少的命令后重新运行脚本${NC}"
exit 1
fi
}
# 脚本入口
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
show_help
exit 0
if [ "$FOUND_KEYS" == "1" ]; then
echo "✅ 已成功提取密钥和数据,稍后会自动归位。"
else
echo "⚠️ 未扫描到现有密钥,安装后将生成新的。"
fi
# 检查系统要求
check_requirements
# --- 2. 彻底卸载与清理 ---
echo ">>> [2/7] 正在清理旧环境..."
systemctl stop rustdesk-hbbs rustdesk-hbbr 2>/dev/null
systemctl disable rustdesk-hbbs rustdesk-hbbr 2>/dev/null
dpkg -P rustdesk-server-hbbs rustdesk-server-hbbr 2>/dev/null
rm -rf "$DATA_DIR" # 已经备份过了,这里彻底清空保证环境纯净
# 运行主程序
main
# --- 3. 环境准备与 IP 获取 ---
echo ">>> [3/7] 正在准备基础环境..."
apt-get update -q
apt-get install -y curl wget lsof ufw dnsutils
echo " 正在获取公网 IP..."
HOST_IP=$(curl -s4 --connect-timeout 5 ifconfig.me)
[ -z "$HOST_IP" ] && HOST_IP=$(curl -s4 --connect-timeout 5 ip.sb)
if [ -z "$HOST_IP" ]; then
echo "❌ 错误:无法获取公网 IP请检查网络。"
exit 1
fi
echo " 公网 IP: $HOST_IP"
# --- 4. 下载与安装 ---
echo ">>> [4/7] 正在下载并安装..."
URL_HBBS="https://cloudreve.vps3344521.xyz/f/W9tx/rustdesk-server-hbbs_${VERSION}_amd64.deb"
URL_HBBR="https://cloudreve.vps3344521.xyz/f/j3fJ/rustdesk-server-hbbr_${VERSION}_amd64.deb"
# 下载 (带重试逻辑)
wget -O hbbs.deb "$URL_HBBS" || wget -O hbbs.deb "https://github.com/rustdesk/rustdesk-server/releases/download/${VERSION}/rustdesk-server-hbbs_${VERSION}_amd64.deb"
wget -O hbbr.deb "$URL_HBBR" || wget -O hbbr.deb "https://github.com/rustdesk/rustdesk-server/releases/download/${VERSION}/rustdesk-server-hbbr_${VERSION}_amd64.deb"
dpkg -i hbbs.deb hbbr.deb
apt-get install -f -y
rm -f hbbs.deb hbbr.deb
# --- 5. 密钥归位与权限修复 (核心步骤) ---
echo ">>> [5/7] 正在将密钥转移至官方目录..."
mkdir -p "$DATA_DIR"
if [ "$FOUND_KEYS" == "1" ]; then
cp -f "$BACKUP_DIR/"* "$DATA_DIR/"
echo "✅ 密钥已成功迁移回 $DATA_DIR"
# 清理刚才手动在 /root 生成的垃圾文件,保持系统整洁
rm -f /root/id_ed25519 /root/id_ed25519.pub /root/db_v2.sqlite3
else
echo " 无旧密钥,系统将自动生成。"
fi
# 统一修复权限 (非常重要,否则服务起不来)
chown -R root:root "$DATA_DIR"
chmod 755 "$DATA_DIR"
# --- 6. 配置服务 (锁定官方路径) ---
echo ">>> [6/7] 正在配置系统服务..."
cat > /etc/systemd/system/rustdesk-hbbs.service <<EOF
[Unit]
Description=RustDesk ID Server
After=network.target
[Service]
Type=simple
LimitNOFILE=1000000
ExecStart=/usr/bin/hbbs -r ${HOST_IP}:21117 -k _
WorkingDirectory=${DATA_DIR}
Restart=always
User=root
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
cat > /etc/systemd/system/rustdesk-hbbr.service <<EOF
[Unit]
Description=RustDesk Relay Server
After=network.target
[Service]
Type=simple
LimitNOFILE=1000000
ExecStart=/usr/bin/hbbr -k _
WorkingDirectory=${DATA_DIR}
Restart=always
User=root
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# 放行端口
if command -v ufw > /dev/null; then
ufw allow 21115:21119/tcp
ufw allow 21116/udp
fi
# --- 7. 启动与验证 ---
echo ">>> [7/7] 正在启动服务..."
systemctl daemon-reload
systemctl enable --now rustdesk-hbbs rustdesk-hbbr
echo "------------------------------------------------"
echo "✅ 修复完成!密钥已锁定在官方目录: $DATA_DIR"
echo "⏳ 正在读取密钥..."
PUB_KEY="${DATA_DIR}/id_ed25519.pub"
# 循环等待确保文件生成/存在
for i in {1..10}; do
if [ -f "$PUB_KEY" ]; then
break
fi
sleep 1
done
if [ -f "$PUB_KEY" ]; then
echo "------------------------------------------------"
echo "🎉 你的 Key (公钥) 为:"
echo ""
echo -e "\033[32m$(cat "$PUB_KEY")\033[0m"
echo ""
echo "------------------------------------------------"
else
echo "❌ 警告:服务似乎启动失败,未检测到 Key 文件。"
echo "请运行 journalctl -u rustdesk-hbbs -n 20 查看错误日志。"
fi

67
121 Normal file
View File

@@ -0,0 +1,67 @@
cat << 'EOF' > docker_install.sh
#!/bin/bash
# 颜色定义
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m'
echo -e "${GREEN}===== 开始针对 ARM64 设备安装 Docker =====${NC}"
# 1. 彻底清理环境
echo "[1/4] 清理旧的配置与冲突源..."
rm -f /etc/apt/sources.list.d/docker.list*
apt-get remove -y docker docker-engine docker.io containerd runc >/dev/null 2>&1
# 2. 下载适配 aarch64 的官方二进制包
echo "[2/4] 下载 Docker 二进制包 (aarch64)..."
cd /tmp
# 使用静态编译版,不依赖系统版本,兼容性最强
curl -L -o docker-static.tgz https://download.docker.com/linux/static/stable/aarch64/docker-26.1.4.tgz
# 3. 解压并部署
echo "[3/4] 解压并安装二进制文件..."
tar xzvf docker-static.tgz >/dev/null
cp docker/* /usr/bin/
rm -rf docker docker-static.tgz
# 4. 配置并启动服务
echo "[4/4] 配置系统服务..."
# 创建最小化配置
mkdir -p /etc/docker
cat <<DOCKER_CONF > /etc/docker/daemon.json
{
"registry-mirrors": ["https://docker.m.daocloud.io"]
}
DOCKER_CONF
# 编写 systemd 服务文件
cat <<SERVICE_CONF > /etc/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
After=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
Restart=on-failure
[Install]
WantedBy=multi-user.target
SERVICE_CONF
# 启动服务
systemctl daemon-reload
systemctl enable docker
systemctl restart docker
# 结果验证
if docker --version >/dev/null 2>&1; then
echo -e "${GREEN}Docker 安装成功!${NC}"
docker --version
else
echo -e "${RED}安装失败,请检查网络或日志。${NC}"
fi
EOF
# 运行脚本
chmod +x docker_install.sh
./docker_install.sh

View File

@@ -1,6 +1,6 @@
#!/bin/bash
# 简单实用的 Docker 容器管理脚本
# 简单实用的 Docker 容器管理脚本 (优化版)
# 颜色定义
RED='\033[0;31m'
@@ -8,53 +8,83 @@ GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m'
# 检查 Docker
# 检查 Docker 及权限
check_docker() {
if ! command -v docker &> /dev/null; then
echo -e "${RED}Docker安装${NC}"
echo -e "${RED}错误: 未检测到 Docker,请先安装${NC}"
exit 1
fi
# 检查是否有权限执行 docker 命令
if ! docker ps &> /dev/null; then
echo -e "${RED}错误: 当前用户无权运行 Docker 命令。${NC}"
echo -e "${YELLOW}请尝试使用 sudo 运行此脚本,或将用户加入 docker 用户组。${NC}"
exit 1
fi
}
# 格式化输出表头
print_table_header() {
printf "${BLUE}%-5s | %-25s | %-12s | %-20s${NC}\n" "编号" "容器名称" "状态" "镜像"
echo "------|---------------------------|--------------|----------------------"
}
# 格式化输出行
print_table_row() {
printf "%-5s | %-25s | %-12b | %-20s\n" "$1" "$2" "$3" "$4"
}
# 显示容器列表
show_containers() {
echo -e "\n${BLUE}=== 容器列表 ===${NC}"
echo "编号 | 容器名称 | 状态 | 镜像"
echo "----|----------|------|------"
print_table_header
local count=0
docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" | tail -n +2 | while read line; do
# 获取数据并暂存避免管道导致的子shell变量丢失问题
mapfile -t lines < <(docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" | tail -n +2)
for line in "${lines[@]}"; do
if [ -n "$line" ]; then
count=$((count + 1))
name=$(echo "$line" | awk '{print $1}')
status=$(echo "$line" | awk '{print $2}')
status_raw=$(echo "$line" | awk '{print $2}')
image=$(echo "$line" | awk '{for(i=3;i<=NF;i++) printf $i" "; print ""}' | sed 's/ $//')
# 状态显示
if [[ "$status" == "Up"* ]]; then
# 截断过长的名称以保持表格整洁
display_name=$name
if [ ${#display_name} -gt 23 ]; then display_name="${display_name:0:20}..."; fi
# 截断过长的镜像名
display_image=$image
if [ ${#display_image} -gt 18 ]; then display_image="${display_image:0:15}..."; fi
# 状态美化
if [[ "$status_raw" == "Up"* ]]; then
status_display="${GREEN}运行中${NC}"
elif [[ "$status" == "Exited"* ]]; then
elif [[ "$status_raw" == "Exited"* ]]; then
status_display="${RED}已停止${NC}"
else
status_display="${YELLOW}$status${NC}"
status_display="${YELLOW}$status_raw${NC}"
fi
echo -e "$count | $name | $status_display | $image"
print_table_row "$count" "$display_name" "$status_display" "$display_image"
fi
done
echo
}
# 显示镜像列表
# 显示镜像列表 (优化对齐)
show_images() {
echo -e "\n${PURPLE}=== 镜像列表 ===${NC}"
echo "编号 | 镜像名称:标签 | 镜像ID | 大小 | 创建时间"
echo "----|---------------|--------|------|----------"
printf "${PURPLE}%-5s | %-30s | %-12s | %-8s | %-15s${NC}\n" "编号" "镜像名称:标签" "镜像ID" "大小" "创建时间"
echo "------|--------------------------------|--------------|----------|----------------"
local count=0
docker images --format "table {{.Repository}}:{{.Tag}}\t{{.ID}}\t{{.Size}}\t{{.CreatedSince}}" | tail -n +2 | while read line; do
mapfile -t lines < <(docker images --format "table {{.Repository}}:{{.Tag}}\t{{.ID}}\t{{.Size}}\t{{.CreatedSince}}" | tail -n +2)
for line in "${lines[@]}"; do
if [ -n "$line" ]; then
count=$((count + 1))
repo_tag=$(echo "$line" | awk '{print $1}')
@@ -62,241 +92,160 @@ show_images() {
size=$(echo "$line" | awk '{print $3}')
created=$(echo "$line" | awk '{for(i=4;i<=NF;i++) printf $i" "; print ""}' | sed 's/ $//')
# 截断过长的镜像名称
if [ ${#repo_tag} -gt 25 ]; then
repo_tag="${repo_tag:0:22}..."
fi
# 截断处理
if [ ${#repo_tag} -gt 28 ]; then repo_tag="${repo_tag:0:25}..."; fi
# 截断镜像ID
image_id_short="${image_id:0:12}"
echo -e "$count | $repo_tag | $image_id_short | $size | $created"
printf "%-5s | %-30s | %-12s | %-8s | %-15s\n" "$count" "$repo_tag" "$image_id" "$size" "$created"
fi
done
echo
}
# 通过编号获取容器名称
get_container_name() {
# 通用获取名称函数 (复用逻辑)
get_name_by_index() {
local number=$1
local count=0
docker ps -a --format "table {{.Names}}" | tail -n +2 | while read name; do
if [ -n "$name" ]; then
count=$((count + 1))
if [ $count -eq $number ]; then
echo "$name"
fi
fi
done
local type=$2 # "container" or "image"
local cmd=""
if [ "$type" == "container" ]; then
cmd="docker ps -a --format '{{.Names}}'"
else
cmd="docker images --format '{{.ID}}'"
fi
# 动态获取第N行
eval "$cmd" | sed -n "${number}p"
}
# 通过编号获取镜像ID
get_image_id() {
local number=$1
local count=0
docker images --format "table {{.ID}}" | tail -n +2 | while read image_id; do
if [ -n "$image_id" ]; then
count=$((count + 1))
if [ $count -eq $number ]; then
echo "$image_id"
fi
fi
done
# 进入容器终端 (新增功能)
enter_container() {
local container_name=$1
echo -e "${YELLOW}尝试进入容器: $container_name${NC}"
echo -e "提示: 输入 ${RED}exit${NC} 可退出容器终端"
echo
# 优先尝试 bash失败则尝试 sh
if docker exec -it "$container_name" /bin/bash 2>/dev/null; then
return
elif docker exec -it "$container_name" /bin/sh 2>/dev/null; then
return
else
echo -e "${RED}无法进入容器终端 (可能容器未包含 bash 或 sh)${NC}"
read -p "按回车键继续..."
fi
}
# 批量删除容器
batch_delete_containers() {
local numbers="$1"
local confirm="$2"
# 处理输入,支持空格和逗号分隔
numbers=$(echo "$numbers" | sed 's/,/ /g')
local success_count=0
local fail_count=0
for number in $numbers; do
if [[ "$number" =~ ^[0-9]+$ ]]; then
container_name=$(get_container_name $number)
container_name=$(get_name_by_index $number "container")
if [ -n "$container_name" ]; then
if [ "$confirm" != "y" ]; then
echo -e "${YELLOW}删除容器: $container_name${NC}"
read -p "确认删除?(Y/n): " confirm_delete
confirm_delete=${confirm_delete:-Y} # 默认Y
if [[ "$confirm_delete" != "y" && "$confirm_delete" != "Y" ]]; then
echo -e "${GREEN}跳过: $container_name${NC}"
continue
fi
read -p "确认删除容器 $container_name? (y/N): " c
[[ "$c" != "y" && "$c" != "Y" ]] && continue
fi
if docker rm -f "$container_name" &> /dev/null; then
echo -e "${GREEN}✓ 删除成功: $container_name${NC}"
success_count=$((success_count + 1))
((success_count++))
else
echo -e "${RED}✗ 删除失败: $container_name${NC}"
fail_count=$((fail_count + 1))
fi
else
echo -e "${RED}✗ 容器编号不存在: $number${NC}"
fail_count=$((fail_count + 1))
echo -e "${RED}✗ 编号 $number 不存在${NC}"
fi
else
echo -e "${RED}✗ 无效编号: $number${NC}"
fail_count=$((fail_count + 1))
fi
done
echo
if [ $success_count -gt 0 ]; then
echo -e "${GREEN}成功删除 $success_count 个容器${NC}"
fi
if [ $fail_count -gt 0 ]; then
echo -e "${RED}删除失败 $fail_count 个${NC}"
fi
[ $success_count -gt 0 ] && echo -e "${GREEN}共删除 $success_count 个容器${NC}"
}
# 批量删除镜像
batch_delete_images() {
local numbers="$1"
local confirm="$2"
# 处理输入,支持空格和逗号分隔
numbers=$(echo "$numbers" | sed 's/,/ /g')
local success_count=0
local fail_count=0
for number in $numbers; do
if [[ "$number" =~ ^[0-9]+$ ]]; then
image_id=$(get_image_id $number)
image_id=$(get_name_by_index $number "image")
if [ -n "$image_id" ]; then
# 获取镜像名称用于显示
image_name=$(docker images --format "table {{.Repository}}:{{.Tag}}\t{{.ID}}" | grep "$image_id" | awk '{print $1}')
# 获取友好名称用于显示
image_name=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "REPOSITORY" | grep "$image_id" | head -n 1)
[ -z "$image_name" ] && image_name=$image_id
if [ "$confirm" != "y" ]; then
echo -e "${YELLOW}删除镜像: $image_name${NC}"
read -p "确认删除?(Y/n): " confirm_delete
confirm_delete=${confirm_delete:-Y} # 默认Y
if [[ "$confirm_delete" != "y" && "$confirm_delete" != "Y" ]]; then
echo -e "${GREEN}跳过: $image_name${NC}"
continue
fi
read -p "确认删除镜像 $image_name? (y/N): " c
[[ "$c" != "y" && "$c" != "Y" ]] && continue
fi
if docker rmi "$image_id" &> /dev/null; then
echo -e "${GREEN}✓ 删除成功: $image_name${NC}"
success_count=$((success_count + 1))
((success_count++))
else
echo -e "${RED}✗ 删除失败: $image_name (可能有容器在使用此镜像)${NC}"
fail_count=$((fail_count + 1))
echo -e "${RED}✗ 删除失败 (可能被容器占用): $image_name${NC}"
fi
else
echo -e "${RED}✗ 镜像编号不存在: $number${NC}"
fail_count=$((fail_count + 1))
fi
else
echo -e "${RED}✗ 无效编号: $number${NC}"
fail_count=$((fail_count + 1))
fi
done
echo
if [ $success_count -gt 0 ]; then
echo -e "${GREEN}成功删除 $success_count 个镜像${NC}"
fi
if [ $fail_count -gt 0 ]; then
echo -e "${RED}删除失败 $fail_count 个${NC}"
fi
}
# 清理悬空镜像
clean_dangling_images() {
echo -e "${YELLOW}清理悬空镜像...${NC}"
local dangling_count=$(docker images -f "dangling=true" -q | wc -l)
if [ $dangling_count -gt 0 ]; then
read -p "确认删除 $dangling_count 个悬空镜像?(Y/n): " confirm_dangling
confirm_dangling=${confirm_dangling:-Y}
if [[ "$confirm_dangling" == "y" || "$confirm_dangling" == "Y" ]]; then
local count=$(docker images -f "dangling=true" -q | wc -l)
if [ "$count" -gt 0 ]; then
read -p "发现 $count 个悬空镜像,是否清理?(y/N): " confirm
if [[ "$confirm" == "y" || "$confirm" == "Y" ]]; then
docker image prune -f
echo -e "${GREEN}清理 $dangling_count 个悬空镜像${NC}"
else
echo -e "${GREEN}取消清理${NC}"
echo -e "${GREEN}清理完成${NC}"
fi
else
echo -e "${GREEN}没有悬空镜像${NC}"
echo -e "${GREEN}系统很干净,没有悬空镜像${NC}"
fi
read -p "按回车键继续..."
}
# 镜像管理菜单
image_management() {
while true; do
clear
echo -e "${PURPLE}"
echo "========================================"
echo " Docker 镜像管理"
echo "========================================"
echo -e "${NC}"
echo -e "${PURPLE}========================================${NC}"
echo -e "${PURPLE} Docker 镜像管理${NC}"
echo -e "${PURPLE}========================================${NC}"
show_images
echo -e "${PURPLE}镜像操作选项:${NC}"
echo "1. 删除镜像 (支持批量: 1 2 3 或 1,2,3)"
echo "2. 批量删除所有镜像"
echo "3. 清理悬空镜像"
echo -e "${PURPLE}操作选项:${NC}"
echo "1. 删除镜像 (例如: 1 或 1,2,3)"
echo "2. 清空所有镜像 (慎用)"
echo "3. 清理悬空镜像 (<none>)"
echo "4. 返回主菜单"
echo
read -p "请选择操作: " choice
read -p "请选择: " choice
case $choice in
1)
echo
echo -e "${YELLOW}删除镜像 (支持批量删除)${NC}"
echo "输入单个编号: 1"
echo "输入多个编号: 1 2 3 或 1,2,3"
echo "输入 all 删除所有镜像"
read -p "请输入镜像编号: " input
if [[ "$input" == "all" ]]; then
echo -e "${RED}警告:将删除所有镜像!${NC}"
read -p "确认删除所有镜像?(Y/n): " confirm_all
confirm_all=${confirm_all:-Y}
if [[ "$confirm_all" == "y" || "$confirm_all" == "Y" ]]; then
total_count=$(docker images -q | wc -l)
docker rmi -f $(docker images -q) &> /dev/null
echo -e "${GREEN}已删除所有 $total_count 个镜像${NC}"
else
echo -e "${GREEN}取消删除${NC}"
fi
else
batch_delete_images "$input" "n"
fi
batch_delete_images "$input" "n"
read -p "按回车键继续..."
;;
2)
echo -e "${RED}警告:删除所有镜像${NC}"
read -p "确认删除所有镜像?(Y/n): " confirm_all
confirm_all=${confirm_all:-Y}
if [[ "$confirm_all" == "y" || "$confirm_all" == "Y" ]]; then
total_count=$(docker images -q | wc -l)
docker rmi -f $(docker images -q) &> /dev/null
echo -e "${GREEN}已删除所有 $total_count 个镜像${NC}"
else
echo -e "${GREEN}取消删除${NC}"
read -p "警告:确定删除所有镜像吗?(yes/N): " confirm
if [ "$confirm" == "yes" ]; then
docker rmi -f $(docker images -q) 2>/dev/null
echo -e "${GREEN}已清空所有镜像${NC}"
fi
read -p "按回车键继续..."
;;
3)
clean_dangling_images
;;
4)
return
;;
*)
echo -e "${RED}无效选择${NC}"
;;
3) clean_dangling_images ;;
4) return ;;
*) echo -e "${RED}无效输入${NC}"; sleep 1 ;;
esac
echo
read -p "按回车键继续..."
done
}
@@ -304,124 +253,74 @@ image_management() {
main_menu() {
while true; do
clear
echo -e "${BLUE}"
echo "========================================"
echo " 简单 Docker 容器管理"
echo "========================================"
echo -e "${NC}"
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE} Docker 容器可视化管理 v2.0${NC}"
echo -e "${BLUE}========================================${NC}"
show_containers
echo -e "${BLUE}容器操作选项:${NC}"
echo "1. 启动容器"
echo "2. 停止容器"
echo "3. 重启容器"
echo "4. 删除容器 (支持批量: 1 2 3 或 1,2,3)"
echo "5. 批量删除所有已停止容器"
echo "6. 查看容器日志"
echo -e "${PURPLE}镜像操作选项:${NC}"
echo "7. 查看和管理镜像"
echo -e "${BLUE}容器操作:${NC} ${CYAN}高级功能:${NC}"
printf "%-35s %-35s\n" "1. 启动容器" "7. 进入容器终端 (Exec)"
printf "%-35s %-35s\n" "2. 停止容器" "8. 实时资源监控 (Stats)"
printf "%-35s %-35s\n" "3. 重启容器" "9. 镜像管理菜单"
printf "%-35s\n" "4. 查看日志"
echo
echo -e "${RED}危险操作:${NC}"
echo "5. 删除容器 (例如: 1 或 1,2,3)"
echo "6. 清理所有已停止容器"
echo "0. 退出"
echo
read -p "请选择操作: " choice
read -p "请选择操作 [0-9]: " choice
# 处理需要选择容器的操作
if [[ "1 2 3 4 7" =~ "$choice" ]]; then
read -p "请输入容器编号: " num
if [[ ! "$num" =~ ^[0-9]+$ ]]; then
echo -e "${RED}请输入有效数字${NC}"; sleep 1; continue
fi
name=$(get_name_by_index $num "container")
if [ -z "$name" ]; then
echo -e "${RED}编号不存在${NC}"; sleep 1; continue
fi
case $choice in
1) docker start "$name" && echo -e "${GREEN}已启动 $name${NC}" ;;
2) docker stop "$name" && echo -e "${GREEN}已停止 $name${NC}" ;;
3) docker restart "$name" && echo -e "${GREEN}已重启 $name${NC}" ;;
4) docker logs -f --tail 100 "$name" ;;
7) enter_container "$name" ;;
esac
[ "$choice" != "7" ] && [ "$choice" != "4" ] && sleep 1
continue
fi
# 处理其他操作
case $choice in
1|2|3|6)
echo
read -p "请输入容器编号: " container_number
if ! [[ "$container_number" =~ ^[0-9]+$ ]]; then
echo -e "${RED}无效的编号${NC}"
read -p "按回车键继续..."
continue
fi
container_name=$(get_container_name $container_number)
if [ -z "$container_name" ]; then
echo -e "${RED}容器编号不存在${NC}"
read -p "按回车键继续..."
continue
fi
case $choice in
1)
echo -e "${YELLOW}启动容器: $container_name${NC}"
docker start "$container_name" && echo -e "${GREEN}启动成功${NC}" || echo -e "${RED}启动失败${NC}"
;;
2)
echo -e "${YELLOW}停止容器: $container_name${NC}"
docker stop "$container_name" && echo -e "${GREEN}停止成功${NC}" || echo -e "${RED}停止失败${NC}"
;;
3)
echo -e "${YELLOW}重启容器: $container_name${NC}"
docker restart "$container_name" && echo -e "${GREEN}重启成功${NC}" || echo -e "${RED}重启失败${NC}"
;;
6)
echo -e "${BLUE}查看容器日志: $container_name${NC}"
echo "按 Ctrl+C 退出"
docker logs -f "$container_name"
continue # 日志查看后直接继续,不等回车
;;
esac
;;
4)
echo
echo -e "${YELLOW}删除容器 (支持批量删除)${NC}"
echo "输入单个编号: 1"
echo "输入多个编号: 1 2 3 或 1,2,3"
echo "输入 all 删除所有容器"
read -p "请输入容器编号: " input
if [[ "$input" == "all" ]]; then
echo -e "${RED}警告:将删除所有容器!${NC}"
read -p "确认删除所有容器?(Y/n): " confirm_all
confirm_all=${confirm_all:-Y}
if [[ "$confirm_all" == "y" || "$confirm_all" == "Y" ]]; then
total_count=$(docker ps -aq | wc -l)
docker rm -f $(docker ps -aq) &> /dev/null
echo -e "${GREEN}已删除所有 $total_count 个容器${NC}"
else
echo -e "${GREEN}取消删除${NC}"
fi
else
batch_delete_containers "$input" "n"
fi
;;
5)
echo -e "${YELLOW}批量删除所有已停止的容器...${NC}"
stopped_count=$(docker ps -aq -f status=exited | wc -l)
if [ $stopped_count -gt 0 ]; then
read -p "确认删除 $stopped_count 个已停止容器?(Y/n): " confirm_stopped
confirm_stopped=${confirm_stopped:-Y}
if [[ "$confirm_stopped" == "y" || "$confirm_stopped" == "Y" ]]; then
docker rm $(docker ps -aq -f status=exited) &> /dev/null
echo -e "${GREEN}已删除 $stopped_count 个已停止容器${NC}"
else
echo -e "${GREEN}取消删除${NC}"
fi
else
echo -e "${GREEN}没有已停止的容器${NC}"
read -p "请输入要删除的容器编号 (支持批量): " nums
batch_delete_containers "$nums" "n"
read -p "按回车键继续..."
;;
6)
read -p "确认清理所有已停止的容器?(y/N): " c
if [[ "$c" == "y" || "$c" == "Y" ]]; then
docker container prune -f
echo -e "${GREEN}清理完成${NC}"
fi
sleep 1
;;
7)
image_management
;;
0)
echo
echo -e "${GREEN}再见!${NC}"
exit 0
;;
*)
echo -e "${RED}无效选择${NC}"
8)
echo -e "${CYAN}正在打开资源监控 (按 Ctrl+C 退出)...${NC}"
docker stats
;;
9) image_management ;;
0) echo -e "${GREEN}再见!${NC}"; exit 0 ;;
*) echo -e "${RED}无效选择${NC}"; sleep 1 ;;
esac
echo
read -p "按回车键继续..."
done
}
# 启动脚本
# 启动
check_docker
main_menu
main_menu

70
GoEdge-cdn Normal file
View File

@@ -0,0 +1,70 @@
# 获取当前系统的操作系统类型(如 Linux
OS=`uname -s`
# 获取当前系统的硬件架构(如 x86_64 或 aarch64
ARCH=`uname -m`
# 初始化 Go 语言对应的架构变量
GOARCH=""
# 定义 GoEdge 的默认安装目录
DIST=/usr/local/goedge
# 检查系统是否安装了 wget 工具
if [ `which wget` ]; then
echo "checking wget ... ok"
else
# 如果没有 wget脚本将无法下载文件直接退出
echo "'wget' command not found"
exit
fi
# 根据系统硬件架构分配对应的下载标识
case "$ARCH" in
"x86_64")
# 64位 Intel/AMD 处理器
GOARCH="amd64"
;;
"aarch64_be"|"aarch64"|"armv8b"|"armv8l"|"armv8"|"arm64")
# 64位 ARM 处理器(如 树莓派、华为鲲鹏、部分云服务器)
GOARCH="arm64"
;;
*)
# 如果是不支持的架构,输出错误并退出
echo "arch '${ARCH}' is not supported yet"
exit
;;
esac
# 拼接 edge-boot 引导程序的下载地址
BOOT_URL="https://dl.goedge.cloud/edge-boot/linux/${GOARCH}/edge-boot"
# 定义引导程序在本地系统的存放路径
BOOT_FILE="/usr/local/bin/edge-boot"
# 如果本地不存在 edge-boot 文件,则开始下载和安装
if [ ! -e $BOOT_FILE ]; then
echo "installing edge-boot to '/usr/local/bin' ..."
# 如果存放路径的目录不存在,则递归创建该目录
if [ ! -d /usr/local/bin ]; then
mkdir -p /usr/local/bin
fi
# 从官网下载 edge-boot 二进制文件
wget $BOOT_URL -O $BOOT_FILE
# 检查文件是否下载成功
if [ ! -f $BOOT_FILE ]; then
echo "download edge-boot failed"
exit
fi
# 赋予该文件所有者可执行权限
chmod u+x $BOOT_FILE
fi
# 输出安装提示信息
echo "installing edge-admin to '${DIST}' ..."
# 调用下载好的引导程序,执行真正的 edge-admin 安装流程
$BOOT_FILE install admin

View File

@@ -10,7 +10,7 @@ set -e
# 定义路径和备份地址
PROJECT_DIR="/data/sublinkx"
COMPOSE_FILE="$PROJECT_DIR/docker-compose.yml"
BACKUP_URL="https://pub-b69a7194f4ea42fba6aa990c49bded91.r2.dev/data/sublinkx.zip"
BACKUP_URL="https://cloudreve.vps3344521.xyz/f/EQT2/sublinkx.zip"
# 检查并安装必要工具 (wget, unzip)
echo "正在检查系统环境..."

44
cl穿透 Normal file
View File

@@ -0,0 +1,44 @@
#!/bin/bash
# 颜色定义
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
echo -e "${GREEN}==== Cloudflare Tunnel Docker 交互安装脚本 ====${NC}"
# 1. 交互式获取 Token
read -p "请输入你的 Cloudflare Tunnel Token: " USER_TOKEN
# 检查输入是否为空
if [ -z "$USER_TOKEN" ]; then
echo -e "${RED}[错误] Token 不能为空!请重新运行脚本并输入有效密钥。${NC}"
exit 1
fi
# 2. 检查并清理同名容器
if [ "$(docker ps -aq -f name=cf-tunnel)" ]; then
echo -e "${YELLOW}[提示] 发现已存在的 cf-tunnel 容器,正在更新...${NC}"
docker rm -f cf-tunnel >/dev/null 2>&1
fi
# 3. 运行 Docker 容器
echo -e "${GREEN}[执行] 正在启动 Cloudflare Tunnel...${NC}"
docker run -d \
--name cf-tunnel \
--restart always \
cloudflare/cloudflared:latest \
tunnel --no-autoupdate run --token "$USER_TOKEN"
# 4. 验证结果
if [ $? -eq 0 ]; then
echo -e "------------------------------------------------"
echo -e "${GREEN}成功Cloudflare Tunnel 已在后台启动!${NC}"
echo -e "容器名称: cf-tunnel"
echo -e "查看日志命令: docker logs -f cf-tunnel"
echo -e "------------------------------------------------"
else
echo -e "${RED}[错误] 容器启动失败,请检查 Docker 是否正常运行。${NC}"
fi

View File

@@ -10,7 +10,7 @@ cat > /root/docker-install-zip.sh <<'EOF'
ZIP_NAME="dockde12.zip"
WORKDIR="/root/docker-offline"
# 主下载地址
URL1="https://freeyx.vps3344.dpdns.org/xui/dockde12.zip"
URL1="https://git.vps3344521.xyz/3344/dock/releases/download/dock%E5%AE%89%E8%A3%85%E5%8C%85/dockde12.zip"
# 备用下载地址
URL2="https://pub-b69a7194f4ea42fba6aa990c49bded91.r2.dev/xui/dockde12.zip"

38
istc Normal file
View File

@@ -0,0 +1,38 @@
cat << 'EOF' > /tmp/update_source.sh
#!/bin/sh
echo "正在执行 iStoreOS 国内源替换脚本..."
# 1. 备份原始配置,防止意外
mkdir -p /etc/opkg/backup
cp /etc/opkg/*.conf /etc/opkg/backup/
echo "已备份原始配置文件到 /etc/opkg/backup/"
# 2. 全量替换为腾讯云镜像 (解决 distfeeds, customfeeds, compatfeeds 等所有文件的连接问题)
# 针对你截图中的 cernet 地址进行精准替换
sed -i 's/mirrors.cernet.edu.cn/mirrors.tencent.com/g' /etc/opkg/*.conf
echo "源地址已修改为腾讯云镜像。"
# 3. 强制更新索引
echo "正在更新软件包索引,请稍候..."
opkg update
# 4. 尝试在线安装 PassWall 缺失的 3 个核心零件
echo "正在安装基础依赖组件..."
opkg install chinadns-ng dns2socks tcping microsocks coreutils-base64 coreutils-nohup
# 5. 检查安装结果
echo "-----------------------------------------------"
if [ -f "/usr/bin/chinadns-ng" ] || [ -f "/usr/bin/dns2socks" ]; then
echo "恭喜!核心零件安装成功。"
echo "现在你可以去 iStore 界面离线安装 PassWall 主程序了。"
echo "或者运行opkg install /tmp/*.ipk --force-depends"
else
echo "部分组件在线安装失败,建议检查路由器联网状态或手动上传零件包。"
fi
echo "-----------------------------------------------"
EOF
# 赋予执行权限并运行
chmod +x /tmp/update_source.sh
/tmp/update_source.sh

65
ru
View File

@@ -23,28 +23,43 @@ if ! command -v docker &> /dev/null; then
exit 1
fi
# 3. 设置安装目录
# 3. 设置安装目录(恢复为原始默认路径)
INSTALL_DIR="/data/rustdesk"
echo -e "${YELLOW}默认安装目录: ${INSTALL_DIR}${PLAIN}"
echo -e "${YELLOW}当前安装目录: ${INSTALL_DIR}${PLAIN}"
# 创建目录
mkdir -p "${INSTALL_DIR}/data"
mkdir -p "${INSTALL_DIR}/api"
# 4. 获取用户输入 (公网IP/域名)
# 4. 获取用户输入
read -p "请输入服务器的公网 IP 或解析好的域名 (必填): " HOST_IP
if [[ -z "$HOST_IP" ]]; then
echo -e "${RED}错误:必须输入 IP 或域名!${PLAIN}"
exit 1
fi
# --- 交互选择:是否需要账号密码登录 ---
echo -e "${YELLOW}是否开启强制登录模式 (MUST_LOGIN)${PLAIN}"
echo -e "1) 需要 (必须注册并登录账号才能连接)"
echo -e "2) 不需要 (直接使用 ID 和 Key 即可连接 - 默认)"
read -p "请选择 [1/2]: " LOGIN_CHOICE
if [[ "$LOGIN_CHOICE" == "1" ]]; then
MUST_LOGIN_VAL="Y"
echo -e "${GREEN}配置已设为:必须登录${PLAIN}"
else
MUST_LOGIN_VAL="N"
echo -e "${GREEN}配置已设为:无需登录(公共模式)${PLAIN}"
fi
# --------------------------------------
# 进入目录
cd "$INSTALL_DIR" || exit
# 5. 生成 docker-compose.yml
echo -e "${YELLOW}正在生成配置文件...${PLAIN}"
# 5. 生成配置文件 (以容器名命名)
echo -e "${YELLOW}正在生成配置文件 rustdesk.yml...${PLAIN}"
cat > docker-compose.yml <<EOF
cat > rustdesk.yml <<EOF
version: '3'
networks:
@@ -64,22 +79,15 @@ services:
- 21119:21119
image: lejianwen/rustdesk-server-s6:latest
environment:
# 公网IP或域名
- RELAY=${HOST_IP}
# 强制必须登录才能连接
- MUST_LOGIN=Y
# 单个连接限速 2MB/s = 16Mb/s
# 动态配置登录限制
- MUST_LOGIN=${MUST_LOGIN_VAL}
- SINGLE_BANDWIDTH=16
# 总带宽限制
- TOTAL_BANDWIDTH=100
# 只允许加密连接
- ENCRYPTED_ONLY=1
# 时区设置
- TZ=Asia/Shanghai
volumes:
# 密钥和数据持久化目录
- ${INSTALL_DIR}/data:/data
# API数据库目录
- ${INSTALL_DIR}/api:/app/data
networks:
- rustdesk-net
@@ -87,35 +95,34 @@ services:
EOF
# 6. 启动容器
echo -e "${YELLOW}正在拉取镜像并启动容器...${PLAIN}"
docker compose pull
docker compose up -d
echo -e "${YELLOW}正在拉取镜像并启动服务...${PLAIN}"
docker compose -f rustdesk.yml pull
docker compose -f rustdesk.yml up -d
# 7. 检查状态并获取 Key
if [ $? -eq 0 ]; then
echo -e "${GREEN}服务启动成功!${PLAIN}"
echo -e "${YELLOW}正在等待密钥生成 (约5秒)...${PLAIN}"
echo -e "${YELLOW}正在等待密钥生成...${PLAIN}"
sleep 5
# 尝试读取公钥
PUB_KEY_FILE="${INSTALL_DIR}/data/id_ed25519.pub"
if [ -f "$PUB_KEY_FILE" ]; then
PUB_KEY=$(cat "$PUB_KEY_FILE")
echo -e "${GREEN}=============================================${PLAIN}"
echo -e " RustDesk Server 部署完成信息"
echo -e " RustDesk Server 部署完成"
echo -e "${GREEN}=============================================${PLAIN}"
echo -e "ID 服务器 (ID Server): ${GREEN}${HOST_IP}${PLAIN}"
echo -e "中继服务器 (Relay Server): ${GREEN}${HOST_IP}${PLAIN}"
echo -e "API 服务器 (API Server): ${GREEN}http://${HOST_IP}:21114${PLAIN}"
echo -e "ID/中继服务器: ${GREEN}${HOST_IP}${PLAIN}"
echo -e "API 服务器: ${GREEN}http://${HOST_IP}:21114${PLAIN}"
echo -e "Key (公钥):"
echo -e "${YELLOW}${PUB_KEY}${PLAIN}"
echo -e "${GREEN}=============================================${PLAIN}"
echo -e "请将以上信息填入 RustDesk 客户端的网络设置中。"
if [[ "$MUST_LOGIN_VAL" == "Y" ]]; then
echo -e "注意:当前为【登录模式】,请先在 API 页面注册账号。"
fi
else
echo -e "${RED}无法自动读取公钥,请手动查目录${INSTALL_DIR}/data${PLAIN}"
echo -e "或者查看日志docker logs rustdesk-server"
echo -e "${RED}未找到公钥,请手动查目录 ${INSTALL_DIR}/data${PLAIN}"
fi
else
echo -e "${RED}服务启动失败,请检查 Docker 日志。${PLAIN}"
fi
echo -e "${RED}服务启动失败${PLAIN}"
fi

83
ru2 Normal file
View File

@@ -0,0 +1,83 @@
cat > install_deb.sh << 'EOF'
#!/bin/bash
# 颜色定义
GREEN='\033[32m'
RED='\033[31m'
YELLOW='\033[33m'
PLAIN='\033[0m'
# 1. 检查 Root 权限
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}错误:请使用 root 用户运行此脚本!${PLAIN}"
exit 1
fi
echo -e "${GREEN}>>> 开始安装 RustDesk Server 1.1.15 (原生 DEB 版) <<<${PLAIN}"
# 2. 清理旧环境 & 安装依赖
echo -e "${YELLOW}正在清理旧版本并安装必要工具...${PLAIN}"
systemctl stop rustdesk-hbbs rustdesk-hbbr 2>/dev/null
apt-get update -y
apt-get install -y wget curl
# 3. 下载软件包
WORK_DIR="/tmp/rustdesk_install"
mkdir -p $WORK_DIR
cd $WORK_DIR
# 你的下载链接
HBBS_URL="https://cloudreve.vps3344521.xyz/f/BOuM/rustdesk-server-hbbs_1.1.15_amd64.deb"
HBBR_URL="https://cloudreve.vps3344521.xyz/f/ZkfN/rustdesk-server-hbbr_1.1.15_amd64.deb"
echo -e "${YELLOW}正在下载 HBBS (ID服务器)...${PLAIN}"
wget -O hbbs.deb $HBBS_URL
echo -e "${YELLOW}正在下载 HBBR (中继服务器)...${PLAIN}"
wget -O hbbr.deb $HBBR_URL
# 4. 执行安装
echo -e "${YELLOW}正在执行安装...${PLAIN}"
apt-get install -y ./hbbs.deb ./hbbr.deb
# 5. 启动服务
echo -e "${YELLOW}正在启动服务...${PLAIN}"
systemctl enable rustdesk-hbbs rustdesk-hbbr
systemctl start rustdesk-hbbs rustdesk-hbbr
# 6. 获取信息
# 获取公网IP
HOST_IP=$(curl -s4 ifconfig.me)
if [[ -z "$HOST_IP" ]]; then
HOST_IP=$(curl -s4 ip.sb)
fi
# 等待密钥生成
sleep 3
# DEB版本默认Key路径: /var/lib/rustdesk-server/
KEY_FILE="/var/lib/rustdesk-server/id_ed25519.pub"
if [ -f "$KEY_FILE" ]; then
PUB_KEY=$(cat "$KEY_FILE")
echo -e "${GREEN}=============================================${PLAIN}"
echo -e " RustDesk Server 1.1.15 安装成功!"
echo -e "${GREEN}=============================================${PLAIN}"
echo -e "ID 服务器: ${GREEN}${HOST_IP}${PLAIN}"
echo -e "中继服务器: ${GREEN}${HOST_IP}:21117${PLAIN}"
echo -e "API 服务器: ${YELLOW}(无/留空)${PLAIN}"
echo -e "Key (公钥):"
echo -e "${YELLOW}${PUB_KEY}${PLAIN}"
echo -e "${GREEN}=============================================${PLAIN}"
echo -e "数据默认目录: /var/lib/rustdesk-server/"
echo -e "如果不通,请务必检查防火墙是否放行 21115-21119 (TCP) 和 21116 (UDP)"
else
echo -e "${RED}安装似乎完成了,但未能读取到 Key。${PLAIN}"
echo -e "请手动检查目录: /var/lib/rustdesk-server/"
fi
# 清理安装包
rm -rf $WORK_DIR
EOF
# 运行脚本
chmod +x install_deb.sh
./install_deb.sh

96
ru2进制下载安装 Normal file
View File

@@ -0,0 +1,96 @@
bash <(curl -sSL https://raw.githubusercontent.com/tech-shrimp/rustdesk-native-install/main/install.sh 2>/dev/null || echo "
#!/bin/bash
# 颜色定义
GREEN='\033[32m'
RED='\033[31m'
YELLOW='\033[33m'
PLAIN='\033[0m'
# 安装目录
INSTALL_DIR='/opt/rustdesk'
WORK_DIR='/vol1/1000/dock/rustdesk_native' # 既然没有Docker我们用这个目录存数据以符合你的习惯
echo -e \"\${GREEN}>>> 开始安装 RustDesk Server (原生版) <<<\${PLAIN}\"
# 1. 准备环境
if [[ \$EUID -ne 0 ]]; then
echo -e \"\${RED}请使用 root 运行!\${PLAIN}\"
exit 1
fi
apt-get update && apt-get install -y wget unzip tar
# 2. 获取 IP
read -p \"请输入服务器公网 IP (必填): \" HOST_IP
if [[ -z \"\$HOST_IP\" ]]; then echo -e \"\${RED}IP 不能为空\${PLAIN}\"; exit 1; fi
# 3. 下载程序 (使用 GitHub 最新稳定版)
mkdir -p \$INSTALL_DIR
mkdir -p \$WORK_DIR
cd \$INSTALL_DIR
echo -e \"\${YELLOW}正在下载 RustDesk 服务端程序...\${PLAIN}\"
# 这里使用固定的稳定版链接,防止获取失败
wget -O rustdesk-server.zip https://github.com/rustdesk/rustdesk-server/releases/download/1.1.11-1/rustdesk-server-linux-amd64.zip
unzip -o rustdesk-server.zip
chmod +x hbbs hbbr
# 4. 创建系统服务 (hbbs - ID服务器)
cat > /etc/systemd/system/rustdesk-hbbs.service <<EOF
[Unit]
Description=RustDesk ID Server
After=network.target
[Service]
Type=simple
LimitNOFILE=1000000
ExecStart=\$INSTALL_DIR/hbbs -r \$HOST_IP -k _
WorkingDirectory=\$WORK_DIR
User=root
Group=root
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# 5. 创建系统服务 (hbbr - 中继服务器)
cat > /etc/systemd/system/rustdesk-hbbr.service <<EOF
[Unit]
Description=RustDesk Relay Server
After=network.target
[Service]
Type=simple
LimitNOFILE=1000000
ExecStart=\$INSTALL_DIR/hbbr -k _
WorkingDirectory=\$WORK_DIR
User=root
Group=root
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# 6. 启动服务
systemctl daemon-reload
systemctl enable rustdesk-hbbs rustdesk-hbbr
systemctl restart rustdesk-hbbs rustdesk-hbbr
# 7. 检查与输出
sleep 3
if systemctl is-active --quiet rustdesk-hbbs; then
PUB_KEY=\$(cat \$WORK_DIR/id_ed25519.pub)
echo -e \"\${GREEN}=============================================\${PLAIN}\"
echo -e \" 原生版 RustDesk 部署成功!\"
echo -e \"\${GREEN}=============================================\${PLAIN}\"
echo -e \"ID 服务器: \${GREEN}\${HOST_IP}\${PLAIN}\"
echo -e \"中继服务器: \${GREEN}\${HOST_IP}\${PLAIN}\"
echo -e \"Key (公钥): \${YELLOW}\${PUB_KEY}\${PLAIN}\"
echo -e \"\${GREEN}=============================================\${PLAIN}\"
echo -e \"数据存储目录: \${WORK_DIR}\"
else
echo -e \"\${RED}启动失败,请检查 systemctl status rustdesk-hbbs\${PLAIN}\"
fi
")

29
ssh程 Normal file
View File

@@ -0,0 +1,29 @@
#!/bin/bash
# 1. 备份原始配置,防止改错
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
echo "已备份原始配置到 /etc/ssh/sshd_config.bak"
# 2. 修改 ListenAddress 确保监听所有接口 (0.0.0.0)
# 这一步解决“只能局域网连,外部连不上”的监听问题
sudo sed -i 's/^#ListenAddress 0.0.0.0/ListenAddress 0.0.0.0/' /etc/ssh/sshd_config
sudo sed -i 's/^ListenAddress ::/#ListenAddress ::/' /etc/ssh/sshd_config
# 3. 允许密码登录 (确保没有被禁用)
sudo sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
sudo sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
# 4. 允许 Root 登录 (可选,视你的安全需求而定)
# 如果你需要远程用 root 登录,请取消下面这行的注释
# sudo sed -i 's/^#PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
# 5. 检查配置文件语法是否正确
sudo sshd -t
if [ $? -eq 0 ]; then
echo "配置检查通过,正在重启 SSH 服务..."
sudo systemctl restart ssh
echo "修复完成!现在 SSH 应该可以接收来自所有接口的连接了。"
else
echo "配置文件修改有误,请检查!"
exit 1
fi

134
te消息转发 Normal file
View File

@@ -0,0 +1,134 @@
#!/bin/bash
# ================= 颜色定义 =================
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
BLUE='\033[34m'
PLAIN='\033[0m'
# ================= 默认配置 =================
DEFAULT_PORT=5005
CONTAINER_NAME="telegram-monitor"
IMAGE_NAME="ghcr.io/riniba/telegrammonitor:latest"
YML_FILE="${CONTAINER_NAME}.yml"
# 检查是否以 root 运行
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}错误: 必须使用 root 用户运行此脚本!${PLAIN}"
exit 1
fi
clear
echo -e "${BLUE}====================================================${PLAIN}"
echo -e "${BLUE} Telegram Monitor 一键部署脚本 (优化版 v2.0) ${PLAIN}"
echo -e "${BLUE}====================================================${PLAIN}"
# 1. 检查 Docker 环境
echo -e "${YELLOW}[1/6] 检查 Docker 环境...${PLAIN}"
if ! command -v docker &> /dev/null; then
echo -e "${RED}未检测到 Docker请先安装 Docker${PLAIN}"
exit 1
fi
echo -e "${GREEN}Docker 已安装。${PLAIN}"
# 2. 设置安装路径
echo -e "${YELLOW}[2/6] 配置安装路径...${PLAIN}"
read -p "请输入安装路径 (默认: $HOME/telegram-monitor): " INSTALL_DIR
if [ -z "$INSTALL_DIR" ]; then
INSTALL_DIR="$HOME/telegram-monitor"
fi
echo -e "安装目录: ${GREEN}$INSTALL_DIR${PLAIN}"
# 创建目录
if [ ! -d "$INSTALL_DIR/data" ]; then
mkdir -p "$INSTALL_DIR/data"
echo -e "已创建数据目录: $INSTALL_DIR/data"
fi
cd "$INSTALL_DIR"
# 3. 设置端口
echo -e "${YELLOW}[3/6] 配置服务端口...${PLAIN}"
read -p "请输入宿主机端口 (默认: $DEFAULT_PORT): " PORT
if [ -z "$PORT" ]; then
PORT=$DEFAULT_PORT
fi
# 检查端口占用
if lsof -Pi :$PORT -sTCP:LISTEN -t >/dev/null ; then
echo -e "${RED}警告: 端口 $PORT 已经被占用!${PLAIN}"
read -p "是否强制继续?(y/n): " FORCE_PORT
if [[ "$FORCE_PORT" != "y" ]]; then
echo "脚本已取消。"
exit 1
fi
fi
echo -e "使用端口: ${GREEN}$PORT${PLAIN}"
# 4. 清理旧容器
echo -e "${YELLOW}[4/6] 清理旧环境...${PLAIN}"
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo -e "${YELLOW}发现同名容器,正在停止并删除...${PLAIN}"
docker stop $CONTAINER_NAME >/dev/null 2>&1
docker rm $CONTAINER_NAME >/dev/null 2>&1
echo -e "${GREEN}旧容器已清理。${PLAIN}"
fi
# 5. 生成配置文件 (符合你的命名习惯)
echo -e "${YELLOW}[5/6] 生成配置文件 $YML_FILE ...${PLAIN}"
cat > $YML_FILE <<EOF
version: '3.8'
services:
telegram-monitor:
image: $IMAGE_NAME
container_name: $CONTAINER_NAME
restart: unless-stopped
ports:
- "$PORT:5005"
volumes:
- ./data:/app
environment:
- ASPNETCORE_ENVIRONMENT=Production
EOF
echo -e "${GREEN}配置文件已生成。${PLAIN}"
# 6. 启动容器与健康检查
echo -e "${YELLOW}[6/6] 拉取镜像并启动容器...${PLAIN}"
# 判断使用 docker compose 还是 docker-compose
if docker compose version >/dev/null 2>&1; then
CMD="docker compose"
elif docker-compose version >/dev/null 2>&1; then
CMD="docker-compose"
else
echo -e "${RED}错误: 未找到 docker-compose 插件。尝试直接使用 docker run 启动...${PLAIN}"
docker run -d --name $CONTAINER_NAME --restart unless-stopped -p $PORT:5005 -v $INSTALL_DIR/data:/app -e ASPNETCORE_ENVIRONMENT=Production $IMAGE_NAME
CMD="docker"
fi
if [ "$CMD" != "docker" ]; then
$CMD -f $YML_FILE up -d
fi
echo -e "${BLUE}正在进行健康检查 (等待 5 秒)...${PLAIN}"
sleep 5
# 检查容器状态
STATUS=$(docker inspect --format='{{.State.Status}}' $CONTAINER_NAME 2>/dev/null)
if [ "$STATUS" == "running" ]; then
IP=$(hostname -I | awk '{print $1}')
echo -e "${BLUE}========================================${PLAIN}"
echo -e "${GREEN}✅ 部署成功!${PLAIN}"
echo -e "容器状态: ${GREEN}$STATUS${PLAIN}"
echo -e "配置文件: $INSTALL_DIR/$YML_FILE"
echo -e "数据目录: $INSTALL_DIR/data"
echo -e "访问地址: ${GREEN}http://$IP:$PORT${PLAIN}"
echo -e "${BLUE}========================================${PLAIN}"
else
echo -e "${BLUE}========================================${PLAIN}"
echo -e "${RED}❌ 部署可能失败,容器状态: $STATUS${PLAIN}"
echo -e "${YELLOW}请运行以下命令查看报错日志:${PLAIN}"
echo -e "docker logs $CONTAINER_NAME"
echo -e "${BLUE}========================================${PLAIN}"
fi

162
xu
View File

@@ -1,10 +1,10 @@
#!/bin/bash
# ==========================================
# 标题:咸v咆哮制作 - X-UI 终极全能版 (V5.6 智能极速版)
# 更新1. 新增源自动测速选择 (Ping检测)
# 2. 新增 Aria2 + Axel 双核多线程下载引擎
# 基底V5.5 (全兼容架构)
# 标题:X-UI 全能安装脚本 (咸V咆哮制作)
# 更新1. 集成定制化架构下载链接
# 2. 模式1与模式2分别对应特定数据库配置
# 3. 智能测速与双核下载引擎
# ==========================================
# --- 颜色配置 ---
@@ -14,11 +14,12 @@ Yellow="\033[33m"
Blue="\033[36m"
Font="\033[0m"
# --- 核心配置 ---
BASE_URL="https://freeyx.vps3344.dpdns.org/xui"
DB_URL_1="https://g1.vps7k7k.xyz/xui/x-ui%E6%A0%87%E5%87%86.db"
DB_URL_2="https://pub-b69a7194f4ea42fba6aa990c49bded91.r2.dev/xui/x-ui%E6%A0%87%E5%87%86.db"
# --- 核心配置 (用户定制) ---
# 数据库链接
DB_URL_PUBLIC="https://git.vps3344521.xyz/attachments/aa8ba64e-3a73-48f4-9317-07e06400b1d8" # 模式1链接
DB_URL_PRIVATE="https://git.vps3344521.xyz/attachments/c457401f-76dd-4499-8ea3-a8b628bc963a" # 模式2链接
# 默认账号设置 (数据库下载后会被重置为此账号)
INSTALL_PATH="/usr/local/x-ui"
BIN_LINK="/usr/bin/x-ui"
DB_PATH="/etc/x-ui/x-ui.db"
@@ -31,13 +32,13 @@ SET_PORT="8443"
# ==========================================
clear
echo -e "${Blue}#################################################${Font}"
echo -e "${Blue}# X-UI 自动安装脚本 (V5.6 智能极速版) #${Font}"
echo -e "${Blue}# X-UI 自动安装脚本 (咸V咆哮制作1.1) #${Font}"
echo -e "${Blue}#################################################${Font}"
echo -e "${Yellow}请选择安装模式:${Font}"
echo -e "${Yellow}请选择安装配置模式:${Font}"
echo -e "-------------------------------------------------"
echo -e "1. ${Green}标准安装${Font} (全新安装,默认空配置)"
echo -e "2. ${Green}恢复安装${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"
@@ -80,27 +81,24 @@ auto_select_source() {
ALIYUN_URL="https://mirrors.aliyun.com"
GOOGLE_URL="https://www.google.com"
# 测速逻辑:获取 HTTP 状态码的时间 (超时设为 2秒)
# 1. 测国外 (Google)
# 测速逻辑
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
# 2. 测国内 (Aliyun)
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
# 3. 决策
# 逻辑:如果 Google 连不上(999) 或者 阿里云速度明显快于 Google则选国内源
# 决策
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}>> 阿里云响应更快 (CN:$SPEED_CN vs Global:$SPEED_GLOBAL),自动选择阿里云源${Font}"
echo -e "${Green}>> 阿里云响应更快,自动选择阿里云源${Font}"
SOURCE_CHOICE="1"
else
echo -e "${Green}>> 国际网络良好 (Global:$SPEED_GLOBAL),自动选择 Cloudflare/官方源${Font}"
echo -e "${Green}>> 国际网络良好,自动选择 Cloudflare/官方源${Font}"
SOURCE_CHOICE="2"
fi
}
@@ -109,7 +107,6 @@ auto_select_source() {
if command -v bc >/dev/null 2>&1 && command -v curl >/dev/null 2>&1; then
auto_select_source
else
# 如果没有 bc 工具默认给个提示让用户盲选或者默认选2
echo -e "${Yellow}缺失测速工具,默认选择官方源...${Font}"
SOURCE_CHOICE="2"
fi
@@ -163,23 +160,17 @@ 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
# [新增] 双核下载引擎
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
@@ -194,7 +185,7 @@ else
fi
# ==========================================
# 5. 时间与架构
# 5. 时间与架构匹配 (定制化下载链接)
# ==========================================
echo -e "${Yellow}>> [3/7] 校准时间...${Font}"
rm -f /etc/localtime
@@ -205,17 +196,50 @@ 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}"
echo -e "${Yellow}>> [4/7] 识别架构并匹配下载源...${Font}"
ARCH=$(uname -m)
DOWNLOAD_URL=""
FILE_NAME=""
# 架构匹配逻辑 - 使用您提供的具体链接
case $ARCH in
x86_64) FILE_NAME="x-ui-linux-amd64.tar.gz" ;;
aarch64) 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" ;;
*) echo -e "${Red}不支持的架构: $ARCH${Font}"; exit 1 ;;
x86_64)
FILE_NAME="x-ui-linux-amd64.tar.gz"
DOWNLOAD_URL="https://git.vps3344521.xyz/attachments/40eeb013-5006-423f-ad74-a0541ab340f4"
;;
aarch64|armv8)
FILE_NAME="x-ui-linux-arm64.tar.gz"
DOWNLOAD_URL="https://git.vps3344521.xyz/attachments/4ab708d5-6bc8-42c0-8494-ef5efe03e074"
;;
i386|i686)
FILE_NAME="x-ui-linux-386.tar.gz"
DOWNLOAD_URL="https://git.vps3344521.xyz/attachments/d1604006-c6b7-4c7c-9652-b42b229ef4cb"
;;
armv5*)
FILE_NAME="x-ui-linux-armv5.tar.gz"
DOWNLOAD_URL="https://git.vps3344521.xyz/attachments/8a5c678c-4ae4-43c4-910d-7e47f7c21c22"
;;
armv6*)
FILE_NAME="x-ui-linux-armv6.tar.gz"
DOWNLOAD_URL="https://git.vps3344521.xyz/attachments/0e7c7fd7-192e-44b3-9739-785a5fb1b51f"
;;
armv7*)
FILE_NAME="x-ui-linux-armv7.tar.gz"
DOWNLOAD_URL="https://git.vps3344521.xyz/attachments/9d1bf416-afb6-4e9f-b46b-ab3a1913a998"
;;
s390x)
FILE_NAME="x-ui-linux-s390x.tar.gz"
DOWNLOAD_URL="https://git.vps3344521.xyz/attachments/18784828-0d20-4bc5-908c-15f91bcf8eb5"
;;
*)
echo -e "${Red}不支持或无法识别的架构: $ARCH${Font}"
exit 1
;;
esac
echo -e "${Green}检测到架构: $ARCH${Font}"
echo -e "${Green}匹配文件名: $FILE_NAME${Font}"
# ==========================================
# 6. 智能下载管理器 (双核+自动回退)
# ==========================================
@@ -225,44 +249,42 @@ download_manager() {
local file=$2
rm -f "$file"
# 优先级 1: Axel (轻量多线程)
# 优先级 1: Axel
if command -v axel >/dev/null 2>&1; then
echo -e "${Green}>> 启用 Axel 引擎 (16线程)...${Font}"
if axel -n 16 -k -q -o "$file" "$url"; then return 0; fi
echo -e "${Red}Axel 下载失败,切换备用引擎...${Font}"
fi
# 优先级 2: Aria2 (强力多线程)
# 优先级 2: Aria2
if command -v aria2c >/dev/null 2>&1; then
echo -e "${Green}>> 启用 Aria2 引擎 (16线程)...${Font}"
# -x16:16连接, -s16:16服务器, -k1M:分块
if aria2c -x 16 -s 16 -k 1M -o "$file" "$url" >/dev/null 2>&1; then return 0; fi
echo -e "${Red}Aria2 下载失败,切换单线程...${Font}"
fi
# 优先级 3: Wget (稳定单线程)
# 优先级 3: Wget
echo -e "${Yellow}>> 启用 Wget (单线程)...${Font}"
if wget $NET_OPT --no-check-certificate --timeout=30 --tries=3 -O "$file" "$url"; then return 0; fi
# 优先级 4: Curl (最后保底)
# 优先级 4: Curl
echo -e "${Yellow}>> 启用 Curl (最后保底)...${Font}"
curl $NET_OPT -L -k --connect-timeout 30 --retry 3 -o "$file" "$url"
}
echo -e "${Yellow}>> [5/7] 下载安装包 (Mode: $NET_OPT)...${Font}"
cd /usr/local/
DOWNLOAD_URL="${BASE_URL}/${FILE_NAME}"
# 调用下载管理器
# 调用下载管理器下载对应架构的文件
download_manager "$DOWNLOAD_URL" "$FILE_NAME"
if ! tar -tzf "$FILE_NAME" >/dev/null 2>&1; then
echo -e "${Red}严重错误:安装包下载失败或文件损坏!${Font}"
echo -e "${Red}尝试链接: $DOWNLOAD_URL${Font}"
exit 1
fi
# ==========================================
# 7. 安装与配置
# 7. 安装与配置 (处理两种模式的数据库)
# ==========================================
echo -e "${Yellow}>> [6/7] 安装与配置...${Font}"
systemctl stop x-ui >/dev/null 2>&1
@@ -273,36 +295,30 @@ 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" == "2" ]; then
echo -e "${Yellow}>> 正在执行恢复模式,下载配置文件...${Font}"
rm -f "$DB_PATH"
# 尝试下载主备份 (使用智能下载器)
download_manager "$DB_URL_1" "$DB_PATH"
# 检查是否成功,失败则尝试备用
if [ ! -s "$DB_PATH" ] || [ $(stat -c%s "$DB_PATH") -lt 1000 ]; then
echo -e "${Red}主链接失败,尝试备用链接...${Font}"
download_manager "$DB_URL_2" "$DB_PATH"
fi
if [ -s "$DB_PATH" ]; then
echo -e "${Green}配置文件恢复成功!${Font}"
else
echo -e "${Red}配置文件下载失败,将降级为标准安装...${Font}"
cp /usr/local/x-ui/bin/x-ui.db "$DB_PATH"
fi
# 确定目标数据库链接
if [ "$INSTALL_MODE" == "1" ]; then
echo -e "${Yellow}>> 正在下载标准/公共配置...${Font}"
TARGET_DB="$DB_URL_PUBLIC"
else
echo -e "${Yellow}>> 执行标准安装...${Font}"
./x-ui setting -port $SET_PORT -username $SET_USER -password $SET_PASS >/dev/null 2>&1
[ ! -f "$DB_PATH" ] && cp /usr/local/x-ui/bin/x-ui.db "$DB_PATH"
echo -e "${Yellow}>> 正在下载私人配置...${Font}"
TARGET_DB="$DB_URL_PRIVATE"
fi
# 下载配置数据库
download_manager "$TARGET_DB" "$DB_PATH"
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"
else
echo -e "${Green}数据库配置下载成功!${Font}"
fi
# --- 统一强制重置账号 ---
# 无论哪种模式,下载下来的数据库密码可能未知,强制重置为脚本头部设定的密码
echo -e "${Yellow}>> 正在强制重置账户权限...${Font}"
systemctl stop x-ui >/dev/null 2>&1
killall x-ui >/dev/null 2>&1
chmod 777 "$DB_PATH" >/dev/null 2>&1
RESET_SUCCESS=0
@@ -360,12 +376,10 @@ IP=$(curl -s4m5 ip.sb)
[ -z "$IP" ] && IP=$(curl -s6m5 ip.sb)
echo -e "\n${Blue}#################################################${Font}"
echo -e "${Green} 咸v咆哮制作 - 安装完成 (V5.6 智能极速版) ${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}"
if [ "$INSTALL_MODE" == "2" ]; then
echo -e "提示 ${Yellow}已成功恢复节点配置,账号密码已重置为 3344${Font}"
fi
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 "标准配置" || echo "私人配置")${Font}"
echo -e "${Blue}#################################################${Font}"