121 lines
3.8 KiB
Bash
121 lines
3.8 KiB
Bash
#!/bin/bash
|
||
#-------------------------------------------------------------------------------------------------------------
|
||
# curl -fsSL https://Git.1-H.CC/Scripts/Linux/raw/branch/2026/devcontainer/apt-install-with-cache.sh | sudo bash -s -- git vim curl
|
||
#-------------------------------------------------------------------------------------------------------------
|
||
|
||
# =================配置区域=================
|
||
# 自定义缓存目录
|
||
CACHE_DIR=${APT_CACHE_DIR:-"/vscode/apt-cache"}
|
||
# 自动更新间隔 (秒),默认 24 小时
|
||
UPDATE_INTERVAL=${APT_UPDATE_INTERVAL:-86400}
|
||
# =========================================
|
||
|
||
START_TIME=$(date +%s)
|
||
trap 'echo "⏱️ 总耗时: $(($(date +%s) - $START_TIME))秒"' EXIT
|
||
|
||
# 确定是否需要 sudo
|
||
SUDO=""
|
||
if [ "$EUID" -ne 0 ]; then
|
||
SUDO="sudo"
|
||
fi
|
||
|
||
# 检查是否有参数传入
|
||
if [ $# -eq 0 ]; then
|
||
echo "用法: $0 <package1> <package2> ..."
|
||
exit 1
|
||
fi
|
||
|
||
PACKAGES="$@"
|
||
|
||
# 创建临时日志文件
|
||
LOG_FILE=$(mktemp)
|
||
$SUDO chmod 666 "$LOG_FILE"
|
||
# env >> "$LOG_FILE"
|
||
|
||
echo "----------------------------------------"
|
||
echo "📦 缓存目录: $CACHE_DIR"
|
||
echo "📝 日志文件: $LOG_FILE"
|
||
echo "🎯 目标软件包: $PACKAGES"
|
||
echo "----------------------------------------"
|
||
|
||
# 1. 准备缓存目录结构
|
||
# apt 需要在 archive 目录下有一个 partial 子目录,否则会报错
|
||
if [ ! -d "$CACHE_DIR/partial" ]; then
|
||
echo "Creating cache directory..."
|
||
$SUDO mkdir -p "$CACHE_DIR/partial"
|
||
fi
|
||
|
||
# 检查上次更新时间
|
||
LAST_UPDATE_FILE="/var/lib/apt/periodic/update-success-stamp"
|
||
NOW=$(date +%s)
|
||
SHOULD_UPDATE=true
|
||
|
||
if [ -f "$LAST_UPDATE_FILE" ]; then
|
||
LAST_UPDATE=$(stat -c %Y "$LAST_UPDATE_FILE" 2>/dev/null || stat -f %m "$LAST_UPDATE_FILE" 2>/dev/null)
|
||
if [ $((NOW - LAST_UPDATE)) -lt $UPDATE_INTERVAL ]; then
|
||
echo "⏩ 软件源在 $(( (NOW - LAST_UPDATE) / 60 )) 分钟前已更新,跳过 update..."
|
||
SHOULD_UPDATE=false
|
||
fi
|
||
fi
|
||
|
||
if [ "$SHOULD_UPDATE" = true ]; then
|
||
echo "🔄 更新软件源..."
|
||
# 自动更新源
|
||
$SUDO apt-get update >> "$LOG_FILE" 2>&1
|
||
if [ $? -ne 0 ]; then
|
||
echo "❌ 更新失败,详细日志:"
|
||
cat "$LOG_FILE"
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# 2. 第一步:只下载,不安装 (Download Only)
|
||
# -o Dir::Cache::archives="$CACHE_DIR" 告诉 apt 把包下载到我们指定的目录
|
||
# --download-only 告诉 apt 只下载依赖包,不要解压安装
|
||
echo "⬇️ 正在检查并下载依赖..."
|
||
$SUDO env DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y --download-only \
|
||
-o Dir::Cache::archives="$CACHE_DIR" \
|
||
$PACKAGES >> "$LOG_FILE" 2>&1
|
||
|
||
if [ $? -ne 0 ]; then
|
||
echo "❌ 下载依赖失败,详细日志:"
|
||
cat "$LOG_FILE"
|
||
exit 1
|
||
fi
|
||
|
||
# 检查缓存命中情况
|
||
if grep -q "Need to get 0 B" "$LOG_FILE"; then
|
||
echo "♻️ 缓存命中:无需下载"
|
||
elif grep -q "Need to get" "$LOG_FILE"; then
|
||
# 尝试提取下载大小,格式通常为 "Need to get XX MB of archives."
|
||
DOWNLOAD_INFO=$(grep "Need to get" "$LOG_FILE")
|
||
echo "⬇️ 缓存未命中:$DOWNLOAD_INFO"
|
||
else
|
||
echo "ℹ️ 无需下载(可能已安装)"
|
||
fi
|
||
|
||
echo "✅ 依赖下载/缓存完成。"
|
||
|
||
# 3. 第二步:安装 (Install)
|
||
# 再次运行 install,指向同一个缓存目录。
|
||
# apt 会检测到目录里已经有对应的 .deb 文件(且哈希值匹配),就会直接使用缓存,跳过下载。
|
||
echo "🚀 开始安装..."
|
||
|
||
# 尝试使用 eatmydata 加速安装 (如果可用)
|
||
APT_CMD="apt-get"
|
||
if command -v eatmydata >/dev/null 2>&1; then
|
||
APT_CMD="eatmydata apt-get"
|
||
echo "⚡️ 启用 eatmydata 加速"
|
||
fi
|
||
|
||
$SUDO env DEBIAN_FRONTEND=noninteractive $APT_CMD install --no-install-recommends -y \
|
||
-o Dir::Cache::archives="$CACHE_DIR" \
|
||
$PACKAGES >> "$LOG_FILE" 2>&1
|
||
|
||
if [ $? -eq 0 ]; then
|
||
echo "🎉 安装成功!"
|
||
else
|
||
echo "❌ 安装失败,详细日志:"
|
||
cat "$LOG_FILE"
|
||
exit 1
|
||
fi |