1. 先搞清楚Linux 安装包到底去哪了很多刚开始用 Linux 的朋友都会遇到同一个困惑——明明执行了安装命令系统也提示安装成功但回头想找那个 .deb 或者 .rpm 文件却怎么也找不到。这不是你操作有问题而是 Linux 包管理器默认压根就没把安装包当成“需要保存的东西”。它更像一个快递员把包裹拆开、把东西放到对应目录然后把快递盒顺手扔了。搞清楚“Linux 下载的安装包位置”这件事最核心的一点是不同发行版、不同包管理器缓存目录完全不一样。比如 Debian/Ubuntu 系的 apt默认下载的 .deb 包会临时放在 /var/cache/apt/archives装完以后如果你不主动清理它其实还躺在那里。而 Red Hat/CentOS 系的 yum/dnf缓存目录在 /var/cache/dnf 下面路径里还会带一层以源 ID 命名的子目录。至于从官网下载的 tar.gz、二进制包位置纯粹取决于你当初用浏览器或 wget 把它存到了哪没有任何“默认”的说法。另外还要注意一件事很多包管理器在安装完成后会自动清理下载缓存或者因为磁盘空间策略只保留最近的包。比如 apt 默认会有“下载完即安装、安装完不一定删”的逻辑但如果你用了 apt autoclean 或 apt clean安装包会被直接清掉。所以你现在去 /var/cache/apt/archives 里看可能是空的这不代表系统没下载过只是已经被清理了。1.1 为什么找不到安装包三个容易被忽略的原因先帮大家定位“找不到”背后的原因不然你方向错了后面怎么找都是白费力气。第一个原因是包管理器直接把下载过程和安装过程做成了“原子操作”。普通用户执行 apt install 就是一条命令下载、校验、解压、安装、配置全在内部完成不会像 Windows 那样给你一个 xxx.exe 让你自己保管。所以很多人的直觉是“安装包应该还在某个地方”其实从用户视角看它只是缓存而已。第二个原因是权限差异。apt、dnf 这类系统级包管理器通常需要 root 权限才能写缓存目录你在普通用户下 sudo 安装生成的缓存文件 owner 是 root。如果你用普通用户去 ls /var/cache/apt/archives可能因为目录权限报错或者看到一堆问号这也会让你误以为文件不存在。第三个原因是文件扩展名不像 Windows 那么直观。.deb、.rpm 这类包在 Linux 桌面环境里可能没有默认关联程序文件管理器不显示预览图标。再加上有些包下载完后名字是一长串带版本号和架构的字符串比如 nginx_1.18.0-6ubuntu14.4_amd64.deb不熟悉的人很容易忽视它觉得自己没下载成功。1.2 不同包管理器的默认缓存位置清单这里我整理了一份常用发行版/包管理器的默认缓存位置建议收藏备用。不同版本的系统可能有细微差异但大方向不会变。发行版/包管理器默认缓存/下载目录说明Debian/Ubuntu (apt)/var/cache/apt/archives已下载的 .deb 包安装后不一定删除Red Hat/CentOS 7 及以下 (yum)/var/cache/yum/xxx/packages以仓库 ID 命名的子目录Red Hat/CentOS 8/Fedora (dnf)/var/cache/dnf/xxx/packages同样带仓库 ID 子目录openSUSE (zypper)/var/cache/zypp/packages默认保留包文件Arch Linux (pacman)/var/cache/pacman/pkg已下载的 .pkg.tar.zst 文件Alpine (apk)/var/cache/apk部分版本默认不保留下载的 .apk 包如果你用的是源码编译安装那么下载的源码包通常在你自己指定的目录比如 /usr/local/src 或 ~/Downloads没有统一标准。这里我特别想提醒一下不要只看目录存在就以为包一定在里面还要检查是不是有 locked 文件标记、是否被定期清理任务删掉了。有一次我在某台 Ubuntu 服务器上找半天最后发现是系统里配了 logrotate 类似的定时任务自动清理了 apt 缓存。所以最稳妥的做法是在你希望保留安装包时直接用“显式下载”的方式而不是从系统缓存里捞。2. 把安装包“抓”到本地的几种姿势前面讲了系统默认的缓存位置但实际工作中我们更需要的往往是主动把安装包下载到指定目录而不是去缓存目录里碰运气。比如内网服务器不能访问外网需要在一台可以联网的机器上下载包再拷进内网。想给多个相同版本的系统做离线批量安装减少重复下载。想保留某个特定版本的包防止软件源更新后旧版本被冲掉。纯粹想把包归档留底方便后续审计。以下方法都是把安装包“主动下载到本地”按包管理器的类型分门别类讲。2.1 从软件源下载到指定目录apt、yum、dnf 的不同玩法对 Debian/Ubuntu 系来说最常用的命令是 apt download。它的作用非常纯粹只下载 .deb 包不安装、不依赖系统状态改变。基本用法# 下载当前源里 nginx 的 .deb 包到当前目录 apt download nginx # 下载指定版本 apt download nginx1.18.0-6ubuntu14.4命令执行后当前目录会出现 nginx_1.18.0-6ubuntu14.4_amd64.deb。这个操作不需要 root 权限因为只是把包从镜像站拉下来不会写系统目录。但有个坑apt download 只会下载你指定的那个主包的 .deb不会自动下载依赖包。如果你想要完整离线安装还需要配合 apt-get download $(apt-cache depends --recurse --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances nginx | grep ^\w | sort -u) 这种依赖递归方式我后面会详细展开。对 RHEL/CentOS 系的 yum有一个很经典的工具叫 yumdownloader它来自 yum-utils 包。用法# 安装 yum-utils如果已安装可跳过 yum install -y yum-utils # 下载 nginx 的 rpm 包包含依赖 yumdownloader --resolve --destdir/root/rpm-packages nginx--resolve 表示同时下载依赖--destdir 指定保存目录。少了 --resolve 的话默认只下载主包。dnf 系自带一个更简单的替代方案dnf download nginx如果需要依赖可以加 --resolve。注意 dnf download 在部分旧版本中需要先安装 dnf-plugins-core。这里有一个容易混淆的点很多人会把 yum install --downloadonly 跟 yumdownloader 搞混。前者更“黑盒”它会在缓存目录里下载完就停止安装但最终文件还是在 /var/cache/yum 下你需要再去 find 一次。而 yumdownloader 是直接把文件写到指定目录更适合脚本化使用。2.2 用 pip 及其他语言包管理器下载“轮子包”Linux 下的“安装包”不只有系统包。Python 生态的 pip 在离线部署时非常常用很多数据分析、运维自动化项目都被它卡过。pip 下载到本地的核心命令是# 下载 Flask 及依赖到 ./wheelhouse 目录 pip download Flask -d ./wheelhouse # 如果需要指定 Python 版本 pip download Flask --python-version 3.9 -d ./wheelhouse # 如果目标机器离线尽量用 --no-deps 或 --platform 配合跨平台下载最常用的场景是为离线服务器准备依赖包。你可以在一台同架构、同 Python 版本的联网机器上执行 pip download然后把整个 wheelhouse 目录拷走目标机器上执行pip install --no-index --find-links./wheelhouse Flask这里的“--no-index”是关键它让 pip 完全忽略 PyPI 远程源只从本地目录找包。如果少了这个参数pip 可能会尝试联网检查版本在离线环境直接报错或卡死。Go 语言也有类似的模块缓存机制go mod download 会把模块源码缓存到 $GOPATH/pkg/mod/cache/download 目录通过 go mod vendor 可以将依赖复制到项目 vendor 目录这个是另一套思路本质也是“下载到本地”。Node.js 的 npm 也有 npm pack、npm cache 等操作如果你主要做前端或全栈项目建议熟悉一下 npm pack它能把某个包打包成 tgz 文件方便离线安装。2.3 直接拉官方二进制包wget 与 curl 的正确操作并不是所有软件都发布在系统软件源里。很多工具比如一些开源数据库、云厂商 CLI、静态二进制工具只提供 GitHub Releases 或者官网下载链接。这时候“下载安装包到本地”的动作就是最原始的 HTTP 下载。# wget 下载到指定文件名 wget -O ./mytool.tar.gz https://example.com/downloads/mytool-2.1.0-linux-amd64.tar.gz # curl 下载并用 tar 解压 curl -L -o ./mytool.tar.gz https://example.com/downloads/mytool-2.1.0-linux-amd64.tar.gz为什么推荐用 -O 指定文件名因为很多下载链接是一串动态参数比如 /download?id123456如果直接 wget保存下来的文件名会是一串看不懂的字符。手动指定文件名后续处理会省心很多。另外下载二进制包后一定要验一下 SHA256。这个习惯很多人没有但在生产环境里非常关键。官方发布页通常会提供对应的 checksum 文件或一串 hash你用 sha256sum 对比一下echo xxxxchecksumxxxx mytool.tar.gz | sha256sum -c -校验失败说明文件可能在传输过程中损坏或者被污染。这种事我在实际工作中遇到过好几次尤其是通过不稳定的内网镜像下载时所以现在不管多急我都会多花十几秒验一下。3. 实操全过程一个干净的下载场景光讲命令不落地永远是纸上谈兵。这一节我带大家完整走一遍“在一台能联网的 Ubuntu 服务器上把 nginx 及其依赖包全部下载到本地再拷到离线机器安装”的流程。整个过程用的都是最常见的工具没有什么特殊环境依赖。3.1 准备工作与参数选择先确定几件事第一目标机器架构。比如目标离线服务器是 amd64你下载的包就必须是 amd64 架构如果下载成 arm64后面拷过去也装不上。uname -m 是最快的确认方式。第二目标机器系统版本。这点很关键Ubuntu 20.04 和 Ubuntu 22.04 的软件源版本差异很大依赖库版本也不同。理想情况是拿同版本系统的机器来下载否则会出现“本地依赖版本满足但目标机器不满足”的问题。第三磁盘空间。如果只是下载 nginx 本身可能不到 1MB但加上依赖搞不好要几十 MB。建议先 df -h 看一下空间。准备命令mkdir -p /data/offline-packages/nginx cd /data/offline-packages/nginx apt-get updateapt-get update 是为了让软件源索引最新防止后续 apt download 提示“找不到软件包”。这一步在离线服务器上没法做所以一定要在联网机器上提前做掉。3.2 分步骤落盘与验证第一步先下载主包apt download nginx此时目录里出现 nginx_xxx_amd64.deb。第二步下载全部依赖。这里我直接给可以直接用的命令apt-get download $(apt-cache depends --recurse --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances nginx | grep ^\w | sort -u)解释一下这个命令在做什么apt-cache depends 会递归列出 nginx 所有依赖项--no-recommends 和 --no-suggests 表示只拿“硬依赖”不拿推荐安装和建议安装的包这样可以显著减小下载体积。grep ^\w 是过滤掉描述行比如“依赖: ”这类说明文字sort -u 去重。最终得到的包名列表全部交给 apt-get download 下载。跑完后 ls 一下你会发现目录里有十几个 .deb其中包含 libc6、libpcre2-8-0、libssl3 等等。这些就是 nginx 能跑起来的基础。第三步校验完整性dpkg-deb -I nginx_*.debdpkg-deb -I 用来查看 deb 包的元信息确认包名、版本、架构与预期一致。还可以用 sha256sum 把每个文件的 hash 记下来方便拷到离线机器后做完整性比对sha256sum *.deb SHA256SUMS3.3 目录规划与版本记录离线安装包里光有文件还不够最好附上一份清单 README把系统版本、源版本、下载时间、安装顺序写清楚。别嫌麻烦我见过太多人拷了一堆包过去结果忘了哪个是主包、哪个是依赖最后只能用 dpkg --info 一个个查。我习惯的目录规划是这样/data/offline-packages/nginx/ ├── SHA256SUMS ├── README.md ├── nginx_1.18.0-6ubuntu14.4_amd64.deb ├── libc6_2.31-0ubuntu9.9_amd64.deb ├── libpcre2-8-0_10.34-7_amd64.deb └── ...README 里至少写三行下载机系统版本Ubuntu 20.04 x86_64下载日期xxxx-xx-xx安装命令sudo dpkg -i *.deb这样一个月以后再翻出来你依然能看懂这套包是为哪个环境准备的。如果只是临时下载一次性使用这个步骤可以不做但如果考虑到“下载安装包到本地”是为了长期维护这步绝不能省。4. 常见问题与排查技巧实录这一节把我在实际运维和日常使用中踩过的坑集中说一遍。每一条都对应过一个真实的“头疼时刻”不是从文档里抄来的。4.1 下载失败或缓存目录里找不到文件场景一apt download 提示“Unable to locate package”。通常原因是软件源列表没更新或者该软件只在某个第三方源里。先跑 apt-get update再看 /etc/apt/sources.list 里是否启用了对应组件比如 universe、multiverse。Ubuntu 默认源里有些包在 main 组件中有些在 universe 中如果没开 universe就会出现找不到包的情况。场景二明明 /var/cache/apt/archives 目录里有文件但拷贝时报权限不足。这个文件的 owner 是 root普通用户没有读权限的话会提示 Permission denied。解决方式有两种sudo cp 过去或者 chmod 改权限。我建议用 sudo cp改目录权限容易影响后续安装。场景三pip download 下载了但目录里没有文件。这里要检查你是不是加了 -d 参数如果不加 -dpip 会下载到临时目录并在下载完成后自动清理。实际表现就是“命令成功了但当前目录什么都没多出来”。同理git clone 这类操作不存在这个问题因为它是直接写到当前目录的。4.2 离线迁移装上后发现依赖缺失这是离线安装最经典的噩梦dpkg -i 主包时提示依赖 libxxx 未安装。因为你下载依赖时用的命令少了某些参数导致关键依赖被漏掉了。我之前在某项目里就犯过这个错。当时用 yumdownloader --resolve 下载某内部工具结果到了离线机器上安装时提示需要 libnss3.so后来一查问题出在源里启用了多个仓库yumdownloader 只解析了默认仓库的依赖而 libnss3 在另一个仓库里。解决办法很简单给 yumdownloader 加 --enablerepo* 或者明确指定仓库名。apt 系也有类似问题常见漏网之鱼是“架构相关依赖”。如果你下载时忘了指定架构或者机器上有 i386 多架构共存的配置apt 可能下载出 i386 的依赖包到 amd64 机器上当然装不上。建议在下载机上确保 dpkg --print-foreign-architectures 里没有多余架构再用 uname -m 核对。4.3 包文件校验不一致或安装包损坏下载完的 .deb 或 .rpm 文件在拷贝、传输、解压过程中都可能损坏。最直观的表现是 dpkg 安装时报“package architecture (amd64) does not match system (arm64)”或者 “cannot access archive: No such file or directory”再或者直接报 “unexpected EOF”。这里我想强调一个很少有人注意的细节U 盘拷贝、scp 传输、甚至网盘下载都可能导致文件内容变化尤其是大文件。文件头几个字节可能没问题但文件末尾被截断了。用 tar 解压时可能还能解出一部分但安装到一半就出幺蛾子。所以不管你用哪种方式传输都要在目标机器上重新算一遍 SHA256。校验命令# 在下载机生成校验文件 sha256sum *.deb SHA256SUMS # 在离线机器上验证 sha256sum -c SHA256SUMS如果校验失败不要犹豫重新下载或重新传输。不要尝试“凑合用一下”安装包损坏带来的问题往往比重新下载麻烦得多。5. 下载到本地之后可以怎么用从离线安装到版本归档既然已经把安装包下载到本地了不妨把它的使用场景也想清楚。很多时候我们下载包并不是为了马上一台机器用而是为了后续的批量部署、版本回滚、甚至内网软件源建设。5.1 离线安装、批量部署与本地源搭建对于一台离线服务器最简单的安装方式就是进到包目录里执行sudo dpkg -i *.deb但如果有依赖顺序问题建议用sudo dpkg -i --force-depends *.deb这个命令要慎用。它忽略依赖关系强制安装包虽然装上了但运行时不一定会少东西。如果你只是想“先把包装进去看看依赖到底缺什么”可以用这种方法诊断问题但不建议在生产环境长期这么干。更稳妥的做法是用 gdebisudo apt-get install gdebi sudo gdebi nginx_*.debgdebi 会自动处理当前目录下的依赖比纯 dpkg 智能不少。但注意 gdebi 本质上还是依赖 apt 源如果离线环境没有本地源它也可能装不上依赖。再进一步如果公司里离线机器很多每次都人工拷包太痛苦可以考虑搭建一个内网软件源。apt 源的精髓是用 apt-ftparchive 或 reprepro 生成 Packages.gz 索引把下载好的 .deb 包放在一个通过 http 或 file 协议能访问的目录里然后离线机器上写一个本地源配置deb [trustedyes] file:///data/mirror/nginx ./这样离线机器也能用 apt install 直接从本地索引安装。配置本地源篇幅比较长这里不展开但思路值得大家记住下载到本地不是终点整理成“可复用资产”才是目的。5.2 我踩过的坑版本锁定与空间清理最后分享几个小经验都是我实际操作里换来的教训。第一不要把“下载到本地”寄托在系统缓存目录上。/var/cache/apt/archives 之类的目录随时可能被 clean而且不同系统策略不一样。我习惯的做法是不管用什么包管理器只要是关键软件都主动用 apt download、yumdownloader、pip download 这类命令把它下到“专门的项目目录”并顺手写好 README。第二注意版本锁定。如果你在测试环境用 apt install nginx某版本 安装成功然后想把这个版本下载下来离线使用一定要先用 apt-cache policy nginx 确认该版本仍在你配置的软件源里。如果源已经更新旧版本可能被移除此时 apt download nginx旧版本 会失败。遇到这种情况只能去官方存档库或者其他可信镜像站手动找。第三控制下载目录体积。一次性下载大量依赖时目录可能会膨胀得很快。之前我在下载某个完整桌面环境依赖时忘了加 --no-recommends结果一下拉下来几百 MB 用不到的包。所以日常使用中记得把 --no-recommends、--no-suggests 记牢只拿必备依赖不拿“推荐安装”。根据我个人经验Linux 下载安装包这件事最需要转变的思维是把“安装”和“下载”看成两件独立的事。系统默认把它们绑在一起但当你需要做离线部署、版本归档或批量运维的时候一定要主动把下载过程“拆”出来用显式命令把安装包固定到你的工作目录里。这套习惯一旦养成以后再遇到内网环境、断网维护、批量装机都会顺很多至少不会在关键时刻翻箱倒柜找缓存目录。