Update Docker镜像源自动测速脚本

This commit is contained in:
2025-10-31 21:16:47 +08:00
committed by GitHub
parent b45d89fc5d
commit 3cb1fcb7a2

View File

@@ -5,77 +5,115 @@ RED='\033[0;31m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
YELLOW='\033[1;33m' YELLOW='\033[1;33m'
BLUE='\033[0;34m' BLUE='\033[0;34m'
NC='\033[0m' # No Color NC='\033[0m'
echo -e "${BLUE}🐳 Docker镜像源自动测速脚本${NC}" echo -e "${BLUE}🐳 Docker镜像源真实速度测试脚本${NC}"
echo "==================================" echo "======================================"
# 定义测试的镜像源列表 # 定义镜像源
declare -A MIRRORS=( declare -A MIRRORS=(
["阿里云"]="mirrors.aliyun.com" ["阿里云"]="mirrors.aliyun.com"
["中科大"]="mirrors.ustc.edu.cn" ["中科大"]="mirrors.ustc.edu.cn"
["清华"]="mirrors.tuna.tsinghua.edu.cn" ["清华"]="mirrors.tuna.tsinghua.edu.cn"
["华为云"]="repo.huaweicloud.com" ["华为云"]="repo.huaweicloud.com"
["腾讯云"]="mirrors.cloud.tencent.com" ["腾讯云"]="mirrors.cloud.tencent.com"
["网易"]="mirrors.163.com"
) )
# 测试文件(使用一个小文件进行测速 # 使用Docker的实际安装包进行测速更大更真实
TEST_FILE="dists/bookworm/InRelease" TEST_PATHS=(
# 或者使用Docker的实际包文件测试 "docker-ce/pool/stable/amd64/containerd.io_1.7.28-1_amd64.deb"
# TEST_FILE="linux/debian/dists/bookworm/InRelease" "docker-ce/pool/stable/amd64/docker-ce_25.0.5-1~debian.12~bookworm_amd64.deb"
)
# 存储测速结果 # 存储结果
declare -A SPEED_RESULTS declare -A AVG_SPEEDS
declare -A TIME_RESULTS
# 测速函数 # 真实下载测速函数
speed_test() { real_speed_test() {
local mirror_name=$1 local mirror_name=$1
local mirror_url=$2 local mirror_url=$2
echo -e "${YELLOW}测试 ${mirror_name} (${mirror_url})...${NC}" echo -e "${YELLOW}测试 ${mirror_name} (${mirror_url})...${NC}"
# 使用curl进行测速下载一个小文件 local total_speed=0
start_time=$(date +%s.%N) local test_count=0
local max_speed=0
# 测试连接时间和下载速度 # 测试多个文件取平均值
result=$(curl -L --connect-timeout 5 --max-time 10 -o /dev/null -s -w \ for test_path in "${TEST_PATHS[@]}"; do
"time_connect:%{time_connect}\ntime_starttransfer:%{time_starttransfer}\ntime_total:%{time_total}\nspeed_download:%{speed_download}" \ local test_url="https://${mirror_url}/${test_path}"
"https://${mirror_url}/${TEST_FILE}" 2>/dev/null)
end_time=$(date +%s.%N) echo -n " 下载测速中..."
# 提取速度信息(字节/秒) # 使用wget进行真实下载测速下载10秒)
speed_download=$(echo "$result" | grep "speed_download" | cut -d':' -f2) local speed_info=$(timeout 10 wget --progress=dot:binary --output-document=/dev/null "$test_url" 2>&1 | grep -o '[0-9.]\+ [KMG]B/s' | tail -1)
time_total=$(echo "$result" | grep "time_total" | cut -d':' -f2)
# 转换为KB/s if [[ $speed_info ]]; then
if [[ $speed_download =~ ^[0-9]+([.][0-9]+)?$ ]]; then # 提取速度数值
speed_kbs=$(echo "scale=2; $speed_download / 1024" | bc) local speed_value=$(echo "$speed_info" | awk '{print $1}')
else local speed_unit=$(echo "$speed_info" | awk '{print $2}')
# 统一转换为KB/s
case $speed_unit in
"MB/s")
speed_kbs=$(echo "$speed_value * 1024" | bc -l 2>/dev/null | awk '{printf "%.2f", $1}')
;;
"GB/s")
speed_kbs=$(echo "$speed_value * 1024 * 1024" | bc -l 2>/dev/null | awk '{printf "%.2f", $1}')
;;
"KB/s")
speed_kbs=$speed_value
;;
*)
speed_kbs=0 speed_kbs=0
;;
esac
if [[ $speed_kbs != "0" ]]; then
echo -e " ${GREEN}$speed_info ≈ $(echo "$speed_kbs" | awk '{printf "%.0f", $1}') KB/s${NC}"
total_speed=$(echo "$total_speed + $speed_kbs" | bc -l)
test_count=$((test_count + 1))
# 记录最大速度
if (( $(echo "$speed_kbs > $max_speed" | bc -l) )); then
max_speed=$speed_kbs
fi
else
echo -e " ${RED}测速失败${NC}"
fi
else
echo -e " ${RED}无法连接${NC}"
fi fi
# 计算响应时间(毫秒) sleep 1
response_time=$(echo "scale=2; $time_total * 1000" | bc 2>/dev/null || echo "0") done
# 存储结果 # 计算平均速度
SPEED_RESULTS["$mirror_name"]=$speed_kbs if [[ $test_count -gt 0 ]]; then
TIME_RESULTS["$mirror_name"]=$response_time local avg_speed=$(echo "scale=2; $total_speed / $test_count" | bc -l)
AVG_SPEEDS["$mirror_name"]=$avg_speed
if [ $(echo "$speed_kbs > 0" | bc) -eq 1 ]; then echo -e " ${GREEN}✅ 平均速度: $(echo "$avg_speed" | awk '{printf "%.0f", $1}') KB/s (峰值: $(echo "$max_speed" | awk '{printf "%.0f", $1}') KB/s)${NC}"
echo -e "${GREEN} ✓ 速度: ${speed_kbs} KB/s, 响应时间: ${response_time}ms${NC}"
else else
echo -e "${RED} ✗ 连接失败或超时${NC}" AVG_SPEEDS["$mirror_name"]=0
SPEED_RESULTS["$mirror_name"]=0 echo -e " ${RED}❌ 所有测速失败${NC}"
TIME_RESULTS["$mirror_name"]=9999
fi fi
echo "" echo ""
} }
# 更换源的函数 # 备用测速方法使用speedtest-cli
network_benchmark() {
echo -e "${BLUE}🌐 进行网络基准测试...${NC}"
if command -v speedtest-cli &> /dev/null; then
speedtest-cli --simple
else
echo "安装speedtest-cli: sudo apt install speedtest-cli"
fi
echo ""
}
# 更换镜像源
change_mirror() { change_mirror() {
local fastest_mirror=$1 local fastest_mirror=$1
local fastest_url=$2 local fastest_url=$2
@@ -83,88 +121,66 @@ change_mirror() {
echo -e "${GREEN}🎯 切换到最快的镜像源: ${fastest_mirror}${NC}" echo -e "${GREEN}🎯 切换到最快的镜像源: ${fastest_mirror}${NC}"
# 备份原配置 # 备份原配置
if [ -f "/etc/apt/sources.list.d/docker.list" ]; then sudo cp /etc/apt/sources.list.d/docker.list /etc/apt/sources.list.d/docker.list.bak.$(date +%Y%m%d_%H%M%S) 2>/dev/null || true
sudo cp /etc/apt/sources.list.d/docker.list /etc/apt/sources.list.d/docker.list.bak.$(date +%Y%m%d_%H%M%S)
fi
# 创建新的Docker源配置 # 创建新的Docker源配置
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null <<EOF sudo tee /etc/apt/sources.list.d/docker.list > /dev/null <<EOF
deb [arch=amd64] https://${fastest_url}/docker-ce/linux/debian bookworm stable deb [arch=amd64] https://${fastest_url}/docker-ce/linux/debian bookworm stable
EOF EOF
echo -e "${GREEN}✅ 已更新Docker镜像源为: ${fastest_mirror}${NC}" echo -e "${GREEN}✅ 已更新Docker镜像源${NC}"
echo -e "${BLUE}🔄 更新软件包列表...${NC}"
sudo apt update sudo apt update
} }
# 主函数
main() { main() {
echo -e "${BLUE}📡 开始测试各镜像源速度...${NC}" # 先进行网络基准测试
network_benchmark
echo -e "${BLUE}📡 开始真实下载速度测试...${NC}"
echo -e "${YELLOW}注意:这将实际下载部分文件,需要较长时间${NC}"
echo "" echo ""
# 检查依赖
if ! command -v wget &> /dev/null; then
echo "安装wget: sudo apt install wget"
sudo apt update && sudo apt install -y wget bc
fi
# 测试所有镜像源 # 测试所有镜像源
for mirror_name in "${!MIRRORS[@]}"; do for mirror_name in "${!MIRRORS[@]}"; do
speed_test "$mirror_name" "${MIRRORS[$mirror_name]}" real_speed_test "$mirror_name" "${MIRRORS[$mirror_name]}"
sleep 1 # 避免请求过于频繁
done done
# 找出最快的镜像源 # 找出最快的
fastest_mirror="" fastest_mirror=""
fastest_speed=0 fastest_speed=0
fastest_time=9999
echo -e "${BLUE}📊 测速结果汇总:${NC}" echo -e "${BLUE}📊 最终测速结果:${NC}"
echo "==================================" echo "======================================"
for mirror_name in "${!SPEED_RESULTS[@]}"; do for mirror_name in "${!AVG_SPEEDS[@]}"; do
speed=${SPEED_RESULTS[$mirror_name]} speed=${AVG_SPEEDS[$mirror_name]}
time=${TIME_RESULTS[$mirror_name]} echo -e " ${mirror_name}: $(echo "$speed" | awk '{printf "%.0f", $1}') KB/s"
if [ $(echo "$speed > 0" | bc) -eq 1 ]; then if (( $(echo "$speed > $fastest_speed" | bc -l) )); then
echo -e " ${mirror_name}: ${speed} KB/s, ${time}ms"
# 选择策略:优先速度,速度相近时选择响应时间短的
if [ $(echo "$speed > $fastest_speed" | bc) -eq 1 ] || \
[ $(echo "$speed == $fastest_speed && $time < $fastest_time" | bc) -eq 1 ]; then
fastest_speed=$speed fastest_speed=$speed
fastest_time=$time
fastest_mirror=$mirror_name fastest_mirror=$mirror_name
fi fi
fi
done done
echo "" echo ""
if [ -n "$fastest_mirror" ] && [ $(echo "$fastest_speed > 0" | bc) -eq 1 ]; then if [[ -n "$fastest_mirror" && $(echo "$fastest_speed > 10" | bc -l) -eq 1 ]]; then
echo -e "${GREEN}🚀 最快的镜像源: ${fastest_mirror}${NC}" echo -e "${GREEN}🚀 推荐镜像源: ${fastest_mirror}${NC}"
echo -e "${GREEN}📈 速度: ${fastest_speed} KB/s, 响应时间: ${fastest_time}ms${NC}" echo -e "${GREEN}📈 平均速度: $(echo "$fastest_speed" | awk '{printf "%.0f", $1}') KB/s${NC}"
echo ""
read -p "是否立即更换为此镜像源?(y/N): " confirm read -p "是否更换镜像源?(y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then if [[ $confirm =~ ^[Yy]$ ]]; then
change_mirror "$fastest_mirror" "${MIRRORS[$fastest_mirror]}" change_mirror "$fastest_mirror" "${MIRRORS[$fastest_mirror]}"
else
echo -e "${YELLOW}未更换镜像源。${NC}"
fi fi
else else
echo -e "${RED}❌ 所有镜像源测试失败,请检查网络连接${NC}" echo -e "${RED}❌ 网络状况不佳,建议检查网络连接${NC}"
fi fi
} }
# 检查依赖
check_dependencies() {
if ! command -v curl &> /dev/null; then
echo -e "${RED}❌ 需要安装 curl${NC}"
sudo apt update && sudo apt install -y curl
fi
if ! command -v bc &> /dev/null; then
echo -e "${RED}❌ 需要安装 bc${NC}"
sudo apt update && sudo apt install -y bc
fi
}
# 运行脚本
check_dependencies
main main