当前位置: 首页 > article >正文

【脚本 完全参数化的通用 APT 源配置方案-Debian/Ubuntu】

通过脚本在 Debian/Ubuntu 系统上一键切换 APT 源

如Dockerfile中 使用某个源(比如 aliyun)

假设你的目录结构是:

.
├── Dockerfile
└── switch-apt-source.sh
FROM ubuntu:22.04# 把脚本拷贝到镜像中
COPY switch-apt-source.sh /usr/local/bin/switch-apt-source.sh# 赋可执行权限并执行脚本,切换为 aliyun 源,然后更新并安装示例软件
RUN chmod +x /usr/local/bin/switch-apt-source.sh \&& /usr/local/bin/switch-apt-source.sh -s aliyun  --clean-cache --remove-extra-sources -y  \&& apt-get install -y curl vim  \&& rm -rf /var/lib/apt/lists/*

使用指南

脚本版本: switch-apt-source.sh v1.0.7
可用镜像源:

  • huawei (HTTP)-华为(默认)

  • aliyun (HTTP)-阿里

  • ustc (HTTPS)-中科大

  • tsinghua (HTTPS)-清华

  • official (HTTP)-官方

Usage: ./apt.sh [ -s <source_name> ] [ -r ] [ --dry-run ] [ --clean-cache ] [ --remove-extra-sources ] [-y]

-h 帮助
-s|–source 指定要切换的镜像源(默认为 huawei)
-r|–with-src 额外写入 deb-src 源行(源码包)
–dry-run 仅打印最终会写入的内容,不实际覆盖源文件
–clean-cache 切换完源后自动执行 apt-get update && apt-get autoclean
–remove-extra-sources 移除 /etc/apt/sources.list.d/ 目录下的所有额外源
-y|–assume-yes 自动回答所有提示为 yes(适用于自动化场景)

示例:
./apt.sh -h
./apt.sh -s aliyun
./apt.sh --source tsinghua --with-src -y
./apt.sh -s ustc --dry-run
./apt.sh -s official --clean-cache --remove-extra-sources -y

#!/usr/bin/env bash
#
# switch-apt-source.sh
# 用于在 Debian/Ubuntu 系统上一键切换 APT 源
#
# Usage:
#   ./switch-apt-source.sh -s <source_name> [-r] [--dry-run] [--clean-cache] [--remove-extra-sources] [-y]
#
# 可选 source_name:
#   huawei      -> 华为云镜像 (HTTP)
#   aliyun      -> 阿里云镜像 (HTTP)
#   tsinghua    -> 清华大学 TUNA 镜像 (HTTPS)
#   ustc        -> 中国科学技术大学镜像 (HTTPS)
#   official    -> 官方默认镜像 (HTTP)
#   (默认使用 huawei)
#
# 主要优化:
# 1. 智能处理 HTTPS 源依赖问题
# 2. 减少不必要的包安装
# 3. 提高切换速度
# 4. 增强最小化系统兼容性set -euo pipefail#################################
# 0. 常量与全局变量            #
#################################
SCRIPT_VERSION="1.0.7"
BACKUP_DIR="/var/backups/apt-sources"
SRC_FILE="/etc/apt/sources.list"
SRC_DIR="/etc/apt/sources.list.d"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)# 颜色定义
RED='\033[1;31m'
GREEN='\033[1;32m'
BLUE='\033[1;34m'
YELLOW='\033[1;33m'
NC='\033[0m'  # No Color#################################
# 1. 镜像源配置                #
#################################
declare -A MIRROR_CONFIG=(# 名称  Debian基础URL                           Debian安全URL                        Ubuntu基础URL                           Ubuntu安全URL[huawei]="http://repo.huaweicloud.com/debian         http://repo.huaweicloud.com/debian-security    http://repo.huaweicloud.com/ubuntu         http://repo.huaweicloud.com/ubuntu"[aliyun]="http://mirrors.aliyun.com/debian           http://mirrors.aliyun.com/debian-security      http://mirrors.aliyun.com/ubuntu           http://mirrors.aliyun.com/ubuntu"[tsinghua]="https://mirrors.tuna.tsinghua.edu.cn/debian     https://mirrors.tuna.tsinghua.edu.cn/debian-security    https://mirrors.tuna.tsinghua.edu.cn/ubuntu     https://mirrors.tuna.tsinghua.edu.cn/ubuntu"[ustc]="https://mirrors.ustc.edu.cn/debian           https://mirrors.ustc.edu.cn/debian-security    https://mirrors.ustc.edu.cn/ubuntu         https://mirrors.ustc.edu.cn/ubuntu"[official]="http://deb.debian.org/debian             http://security.debian.org/debian-security      http://archive.ubuntu.com/ubuntu           http://security.ubuntu.com/ubuntu"
)# HTTP 回退源(当 HTTPS 失败时使用)
declare -A HTTP_FALLBACKS=([tsinghua]="http://mirrors.tuna.tsinghua.edu.cn"[ustc]="http://mirrors.ustc.edu.cn"
)# 定义 HTTP 源列表
HTTP_SOURCES=("huawei" "aliyun" "official")#################################
# 2. 函数:打印使用说明         #
#################################
print_usage() {echo -e "${BLUE}脚本版本: switch-apt-source.sh v${SCRIPT_VERSION}${NC}"echo -e "${BLUE}可用镜像源:${NC}"for source in "${!MIRROR_CONFIG[@]}"; doif [[ " ${HTTP_SOURCES[*]} " =~ " ${source} " ]]; thenecho "  - $source (HTTP)"elseecho "  - $source (HTTPS)"fidonecat << EOFUsage: $0 [ -s <source_name> ] [ -r ] [ --dry-run ] [ --clean-cache ] [ --remove-extra-sources ] [-y]-s|--source           指定要切换的镜像源(默认为 huawei)-r|--with-src         额外写入 deb-src 源行(源码包)--dry-run             仅打印最终会写入的内容,不实际覆盖源文件--clean-cache         切换完源后自动执行 apt-get update && apt-get autoclean--remove-extra-sources 移除 /etc/apt/sources.list.d/ 目录下的所有额外源-y|--assume-yes       自动回答所有提示为 yes(适用于自动化场景)示例:$0 -s aliyun$0 --source tsinghua --with-src -y$0 -s ustc --dry-run$0 -s official --clean-cache --remove-extra-sources -y
EOFexit 0
}#################################
# 3. 函数:列出可选镜像源       #
#################################
list_sources() {echo -e "${BLUE}支持的镜像源列表:${NC}"for source in "${!MIRROR_CONFIG[@]}"; doif [[ " ${HTTP_SOURCES[*]} " =~ " ${source} " ]]; thenecho "  - $source (HTTP)"elseecho "  - $source (HTTPS)"fidoneexit 0
}#################################
# 4. 函数:检查 HTTPS 依赖     #
#################################
check_https_dependencies() {# 仅对 HTTPS 源检查依赖if [[ " ${HTTP_SOURCES[*]} " =~ " ${SOURCE_NAME} " ]]; thenreturn 0  # HTTP 源不需要额外依赖fi# 检查是否已安装 ca-certificatesif ! dpkg -s ca-certificates &>/dev/null; thenecho -e "${RED}错误:系统缺少 ca-certificates 包,无法访问 HTTPS 源${NC}"echo -e "${YELLOW}请先安装 ca-certificates:apt-get install -y ca-certificates${NC}"# 检查是否有 HTTP 回退源if [[ -n "${HTTP_FALLBACKS[$SOURCE_NAME]:-}" ]]; thenif [[ "$ASSUME_YES" == true ]]; thenecho -e "${YELLOW}自动回退到 HTTP 源...${NC}"BASE_URL="http://${BASE_URL#*://}"SECURITY_URL="http://${SECURITY_URL#*://}"return 0elseecho -e "${YELLOW}是否回退到 HTTP 源?(y/N)${NC}"read -rp " " ynif [[ "$yn" =~ ^[Yy]$ ]]; thenecho -e "${YELLOW}正在回退到 HTTP 源...${NC}"BASE_URL="http://${BASE_URL#*://}"SECURITY_URL="http://${SECURITY_URL#*://}"return 0fififiexit 1fireturn 0
}
#################################
# 5. 参数解析                  #
#################################
SOURCE_NAME="huawei"   # 默认华为源
ADD_DEBSRC=false       # 是否写入 deb-src
DRY_RUN=false          # 是否仅打印,不实际覆盖
CLEAN_CACHE=false      # 是否切换完后自动清理缓存
REMOVE_EXTRA_SOURCES=false # 是否移除额外源
ASSUME_YES=false       # 是否自动回答 yeswhile [[ $# -gt 0 ]]; docase "$1" in-s|--source)if [[ -n "${2-}" && ! "$2" =~ ^- ]]; thenSOURCE_NAME="$2"shiftelseecho -e "${RED}错误:-s/--source 选项缺少参数${NC}"exit 1fi;;--source=*)SOURCE_NAME="${1#*=}";;-r|--with-src)ADD_DEBSRC=true;;--dry-run)DRY_RUN=true;;--clean-cache)CLEAN_CACHE=true;;--remove-extra-sources)REMOVE_EXTRA_SOURCES=true;;-y|--assume-yes)ASSUME_YES=true;;-l|--list)list_sources;;-h|--help)print_usage;;*)echo -e "${RED}错误:未知选项 '$1'${NC}"print_usageexit 1;;esacshift
done#################################
# 6. 验证镜像源名称是否有效     #
#################################
if [[ -z "${MIRROR_CONFIG[$SOURCE_NAME]-}" ]]; thenecho -e "${RED}错误:不支持的镜像源 '${SOURCE_NAME}'${NC}"echo -e "${BLUE}可用源:${NC}"for source in "${!MIRROR_CONFIG[@]}"; doecho "  - $source"doneexit 1
fi#################################
# 7. 检查是否以 root 执行       #
#################################
if [[ $EUID -ne 0 ]]; thenecho -e "${RED}错误:请使用 root 权限运行此脚本${NC}"exit 1
fi#################################
# 8. 获取操作系统信息          #
#################################
if [[ ! -f /etc/os-release ]]; thenecho -e "${RED}错误:无法识别操作系统,请确保是 Debian/Ubuntu 系统。${NC}"exit 1
fi# 加载系统信息
. /etc/os-release
DIST_ID=$(echo "${ID:-unknown}" | tr '[:upper:]' '[:lower:]')
DIST_CODENAME=$(echo "${VERSION_CODENAME:-}" | tr '[:upper:]' '[:lower:]')if [[ -z "$DIST_CODENAME" ]]; then# 尝试使用 lsb_release 获取版本代号if command -v lsb_release &>/dev/null; thenDIST_CODENAME=$(lsb_release -cs)elseecho -e "${YELLOW}警告:无法获取系统版本代号,使用默认值 bookworm${NC}"DIST_CODENAME="bookworm"fi
fi# 获取 Debian 主版本号
DEB_MAJOR_VERSION=""
if [[ "$DIST_ID" == "debian" ]]; thenDEB_MAJOR_VERSION=$(echo "${VERSION_ID:-}" | cut -d. -f1)
fi# 系统架构
DIST_ARCH=$(dpkg --print-architecture)#################################
# 9. 解析镜像配置              #
#################################
read -r -a URLS <<< "${MIRROR_CONFIG[$SOURCE_NAME]}"
if [[ ${#URLS[@]} -lt 4 ]]; thenecho -e "${RED}错误:镜像源配置不完整,请检查脚本配置${NC}"exit 1
fi# 根据系统类型选择 URL
if [[ "$DIST_ID" == "debian" ]]; thenBASE_URL="${URLS[0]}"SECURITY_URL="${URLS[1]}"
elseBASE_URL="${URLS[2]}"SECURITY_URL="${URLS[3]}"
fi# 检查 HTTPS 依赖
HAS_CURL=false
if check_https_dependencies; thenHAS_CURL=true
fi#################################
# 10. 设置组件和安全源路径     #
#################################
if [[ "$DIST_ID" == "debian" ]]; thenCOMPONENTS="main contrib non-free"# Debian 12+ 默认再加 non-free-firmwareif [[ -n "$DEB_MAJOR_VERSION" && "$DEB_MAJOR_VERSION" -ge 12 ]]; thenCOMPONENTS="${COMPONENTS} non-free-firmware"fi# 安全源路径:Debian 9 及更早 "<codename>/updates",10+ "<codename>-security"if [[ -n "$DEB_MAJOR_VERSION" && "$DEB_MAJOR_VERSION" -lt 10 ]]; thenSECURITY_SUITE="${DIST_CODENAME}/updates"elseSECURITY_SUITE="${DIST_CODENAME}-security"fi
else# Ubuntu 系列COMPONENTS="main restricted universe multiverse"SECURITY_SUITE="${DIST_CODENAME}-security"
fi#################################
# 11. 备份与旧备份自动清理      #
#################################
mkdir -p "$BACKUP_DIR"# 自动清理旧备份
if [[ $(find "$BACKUP_DIR" -type f -name 'sources.list.bak.*' 2>/dev/null | wc -l) -gt 0 ]]; thenfind "$BACKUP_DIR" -type f -name 'sources.list.bak.*' -mtime +30 -delete 2>/dev/null || true
fiBACKUP_FILE="${BACKUP_DIR}/sources.list.bak.${TIMESTAMP}"# 检查源文件状态
if [[ ! -e "$SRC_FILE" ]]; then[[ "$ASSUME_YES" == false ]] && echo -e "${YELLOW}源文件不存在,自动创建新文件${NC}"touch "$SRC_FILE"chmod 644 "$SRC_FILE"
elif [[ ! -s "$SRC_FILE" ]]; then[[ "$ASSUME_YES" == false ]] && echo -e "${YELLOW}源文件为空,继续写入新配置${NC}"
fi# 文件权限检查
if [[ -e "$SRC_FILE" && ! -w "$SRC_FILE" ]]; thenchmod u+w "$SRC_FILE"
fiecho "正在备份原文件: ${SRC_FILE} -> ${BACKUP_FILE}"
cp -f "$SRC_FILE" "$BACKUP_FILE"#################################
# 12. 处理额外源 (可选)        #
#################################
if [[ "$REMOVE_EXTRA_SOURCES" == true ]]; then[[ "$ASSUME_YES" == false ]] && echo -e "${YELLOW}正在移除额外源...${NC}"if [[ -d "$SRC_DIR" ]]; thenBACKUP_EXTRA_DIR="${BACKUP_DIR}/sources.list.d.${TIMESTAMP}"mkdir -p "$BACKUP_EXTRA_DIR"if find "$SRC_DIR" -maxdepth 1 -type f | grep -q .; thenmv -f "${SRC_DIR}"/* "$BACKUP_EXTRA_DIR/" 2>/dev/null || true[[ "$ASSUME_YES" == false ]] && echo -e "${GREEN}已备份并移除额外源到: ${BACKUP_EXTRA_DIR}${NC}"fifi
fi#################################
# 13. 生成临时文件并写入新源   #
#################################
TMPFILE=$(mktemp "/tmp/sources.list.XXXXXX")
chmod 644 "$TMPFILE"{echo "# ${SOURCE_NAME} 镜像源 (自动生成) - ${PRETTY_NAME} [${DIST_ARCH}]"echo "# 生成时间: $(date '+%Y-%m-%d %H:%M:%S')"echo "# 脚本版本: switch-apt-source.sh v${SCRIPT_VERSION}"echo "# 协议: $(echo "$BASE_URL" | cut -d: -f1)"echoecho "deb [arch=${DIST_ARCH}] ${BASE_URL} ${DIST_CODENAME} ${COMPONENTS}"$ADD_DEBSRC && echo "deb-src [arch=${DIST_ARCH}] ${BASE_URL} ${DIST_CODENAME} ${COMPONENTS}"echoecho "deb [arch=${DIST_ARCH}] ${SECURITY_URL} ${SECURITY_SUITE} ${COMPONENTS}"$ADD_DEBSRC && echo "deb-src [arch=${DIST_ARCH}] ${SECURITY_URL} ${SECURITY_SUITE} ${COMPONENTS}"echoecho "deb [arch=${DIST_ARCH}] ${BASE_URL} ${DIST_CODENAME}-updates ${COMPONENTS}"$ADD_DEBSRC && echo "deb-src [arch=${DIST_ARCH}] ${BASE_URL} ${DIST_CODENAME}-updates ${COMPONENTS}"echoecho "deb [arch=${DIST_ARCH}] ${BASE_URL} ${DIST_CODENAME}-backports ${COMPONENTS}"$ADD_DEBSRC && echo "deb-src [arch=${DIST_ARCH}] ${BASE_URL} ${DIST_CODENAME}-backports ${COMPONENTS}"
} > "$TMPFILE"#################################
# 14. Dry-run 模式处理         #
#################################
if [[ "$DRY_RUN" == true ]]; thenecho -e "\n${BLUE}---- Dry-run 模式:以下内容将写入 ${SRC_FILE} ----${NC}"cat "$TMPFILE"rm -f "$TMPFILE"echo -e "\n${GREEN}✓ Dry-run 完成,未实际覆盖任何文件。${NC}"exit 0
fi#################################
# 15. 原子替换 sources.list    #
#################################
mv -f "$TMPFILE" "$SRC_FILE"echo -e "\n${GREEN}✓ 已成功将 APT 源切换为: ${SOURCE_NAME}${NC}"
echo "主仓库: ${BASE_URL}"
echo "安全更新: ${SECURITY_URL}"
echo "组件: ${COMPONENTS}"
$ADD_DEBSRC && echo "已额外写入 deb-src 行。"#################################
# 16. 后续操作提示             #
#################################
echo -e "\n${BLUE}▷ 下一步操作建议:${NC}"
echo "  1. 更新软件包列表: apt update"
echo "  2. 升级所有软件包: apt upgrade"echo -e "\n${BLUE}▷ 回滚方法:${NC}"
echo "  cp -v ${BACKUP_FILE} ${SRC_FILE}"
[[ "$REMOVE_EXTRA_SOURCES" == true ]] && echo "  mv ${BACKUP_EXTRA_DIR}/* ${SRC_DIR}/"#################################
# 17. 清理缓存(可选)         #
#################################
if [[ "$CLEAN_CACHE" == true ]]; thenecho -e "\n${BLUE}正在执行 apt-get update && apt-get autoclean ...${NC}"if apt-get update -y; thenapt-get autoclean -yecho -e "${GREEN}✓ 缓存清理完成。${NC}"elseecho -e "${YELLOW}警告:apt-get update 失败,跳过 autoclean${NC}"fi
fiexit 0
http://www.lryc.cn/news/2394720.html

相关文章:

  • 数据集笔记:SeekWorld
  • LeetCode 算 法 实 战 - - - 移 除 链 表 元 素、反 转 链 表
  • Jenkins实践(10):pipeline构建历史展示包名和各阶段间传递参数
  • 从头认识AI-----循环神经网络(RNN)
  • 配置远程无密登陆ubuntu服务器时无法连接问题排查
  • 5.31 数学复习笔记 22
  • kafka学习笔记(三、消费者Consumer使用教程——使用实例及及核心流程源码讲解)
  • 鸿蒙 Form Kit(卡片开发服务)
  • 算力卡上部署OCR文本识别服务与测试
  • KWIC—Implicit Invocation
  • Visual Studio 2022 发布独立的 exe 文件
  • 11.4java语言执行浅析4
  • Excel 操作 转图片,转pdf等
  • 说说 Kotlin 中的 Any 与 Java 中的 Object 有何异同?
  • python分配方案数 2023年信息素养大赛复赛/决赛真题 小学组/初中组 python编程挑战赛 真题详细解析
  • 《信号与系统》第 5 章 离散时间傅里叶变换
  • 动态IP与区块链:重构网络信任的底层革命
  • 目前主流图像分类模型的详细对比分析
  • uniapp使用Canvas生成电子名片
  • 世冠科技亮相中汽中心科技周MBDE会议,共探汽车研发数字化转型新路径
  • Linux笔记---线程
  • MCP架构深度解析:从基础原理到核心设计
  • 【监控】pushgateway中间服务组件
  • 数据库暴露--Get型注入攻击
  • AI炼丹日志-26 - crawl4ai 专为 AI 打造的爬虫爬取库 上手指南
  • ESP32-idf学习(四)esp32C3驱动lcd
  • 【python】uv管理器
  • 关于Web安全:7. WebShell 管理与持久化后门
  • 音视频中的复用器
  • 戴尔AI服务器订单激增至121亿美元,但传统业务承压