☰
UOS离线部署实战:apt依赖全量下载与安装指南
2026/10/2 8:49:22 网站建设 项目流程

我去年接手了一个内网办公环境迁移项目,要把几十台旧机器换成统信UOS专业版,但机房物理隔离,没有外网。最头疼的不是系统安装,而是安装软件时那一串串依赖报错——缺一个库,后面一串软件全装不上。折腾了一周之后,我总结出一套用命令行高效下载离线安装包及依赖的完整流程,今天把它整理出来,希望能帮到同样在做UOS离线部署的朋友。

这篇文章的核心就是解决一个问题:在一台能联网的Linux机器上,把UOS专业版需要的软件包以及所有依赖全部下载下来,拿到内网一键装完。内容覆盖apt/dpkg底层机制、三种依赖下载思路、批量自动化脚本、离线安装与修复手段、以及UOS上特有的坑。适合做系统集成、运维、UOS迁移项目的人参考,纯新手建议先把基础命令熟悉一遍。

1. UOS离线部署为何总卡在依赖:先弄懂apt与dpkg的底细

1.1 UOS专业版的包管理血缘:来自Debian,但又不完全一样

统信UOS专业版底层基于Debian,包管理用的是apt加dpkg这套生态。deb包本质上是一个ar压缩包,里面塞了程序文件、控制信息、脚本和依赖声明,dpkg负责把包解开并安放到系统对应目录,apt则负责处理包与包之间的依赖关系、下载、升级等更上层的工作。

这个血缘关系意味着,Debian系的大多数操作在UOS上都能用,比如apt-get install、apt-cache search、dpkg -i。但UOS的源和Debian官方源不是同一个,依赖版本也不完全同步。我试过直接把Debian源里的某个依赖包下载下来往UOS上装,结果版本对不上,系统报错"依赖关系不满足"。所以做UOS离线包,一定要用UOS自己的源,不要想当然去Debian源里抓包。

1.2 依赖地狱:离线场景为什么放大这个问题

在线环境下,你执行一条apt-get install,apt会自己读取每个包的Depends字段,把缺的依赖依次从源里拉下来自动装上。这个过程由apt的依赖解析器全权接管,你基本感知不到依赖的存在。

离线环境下,apt无法访问网络,这个自动解析就瘫痪了。你需要把安装包和依赖全部手动准备好,一层一层剥洋葱:装A需要B,装B需要C,C又依赖D和E……一旦漏掉中间某个包,前面装的全白搭。

举个真实例子,我帮客户装一个办公套件时,它依赖了十几个库文件,其中一个库又依赖低版本的glibc相关模块。漏掉任何一个,dpkg就会中断并告诉你"未安装的软件包 X"。

1.3 哪些场景最需要离线安装包

不是所有UOS装软件都需要离线包。以下场景基本绕不开:

  • 物理隔离内网:机房没有外网,连局域网源都没有,这是最常见的场景。
  • 统一装机基线:多台机器需要在同一时间用同一版本软件部署,防止各台机器从源里拉到不同版本,导致行为不一致。
  • 保密或安全管理要求:不允许在线安装,必须经过人工审查的软件包才能进内网。
  • 网络波动严重:有些单位的外网质量堪忧,安装到一半断线会留下半配置状态,离线包反而更稳。

2. 搭建下载环境:开发者模式、apt源与系统版本基线

2.1 开发者模式:绕不开的第一步

UOS专业版默认不开放root终端,直接执行sudo apt-get可能会提示权限受限。安装部分deb包时需要root权限写入系统目录,所以第一件事是开启开发者模式。

常规做法是:在控制中心找到通用设置,进入开发者模式选项,按提示绑定账号开启。开完之后,在桌面右键打开终端,执行sudo -i验证一下是否具备root权限。开发者模式还能顺手帮你打开SSH,后面批量下发离线包会方便很多。

提示:开发者模式开启后系统会提示安全风险,这是正常提示,离线网络环境下风险可控。如果实在不能开,也可以试试用普通用户配合sudo运行命令,但部分包的postinst脚本会因为没有权限而失败。

2.2 配置apt源:先解决"从哪下载"的问题

下载离线包之前,需要确认下载机上的源列表可用。UOS的源配置文件在/etc/apt/sources.list以及/etc/apt/sources.list.d/目录下。专业版预装的是官方企业源,如果能联网且能正常apt update,直接用就行。

如果你用的是社区版或想指定一个公共源,需要手动改配置。以UOS 20为例,一份可用的源配置大致长这样:

deb [trusted=yes] https://community-packages.deepin.com/beige/ beige main contrib non-free

注意这里的beige是版本代号,不同UOS版本的代号不一样。在动手改源之前,最好先执行cat /etc/os-release确认系统版本和代号,再去匹配对应的源地址。改完源之后必须执行apt update。

2.3 环境评估:下载机和目标机的版本必须对齐

这一步是很多人忽略的关键点。下载离线包时,下载机和目标机的条件要尽可能一致:

  • CPU架构必须一致。UOS支持x86_64、ARM64、LoongArch等架构,用uname -m确认。x86_64的包在ARM机器上装不了。
  • 系统大版本尽量一致,小版本差异较大时,部分依赖包版本会不同。
  • 源配置也尽量一致,否则下载的依赖版本可能和目标机源里的不一致,导致安装时版本冲突。

我最开始犯过一个错:在x86_64的下载机上下了一堆ARM机器的包,结果送去现场全部装不上,来回折腾了好几天。现在我在做离线包前,第一件事就是对比两边机器的/etc/os-release和uname -m输出。

3. 用apt命令把安装包和依赖完整抠出来:三种最实用思路

3.1 最朴素的方案:apt-get download加手动分析依赖

apt-get download的作用是只下载某个软件包的文件,不做任何安装操作。它和apt-get install的区别在于,不检查依赖、不修改系统、不下载依赖包。这给了我们手动控制的空间。

原理搞清楚了,问题是:"依赖列表从哪来?"两个常用命令:

  • apt-cache depends 包名:列出该包的直接依赖、推荐、建议等。
  • dpkg-deb -I 某个.deb文件:查看deb包的控制信息,其中Depends字段就是依赖关系。

Debian系包依赖声明中常见的运算符包括>=、<=、=,比如libc6 (>= 2.34),表示需要libc6版本大于等于2.34。

手动方案的流程是:先用apt-cache depends看直接依赖,然后对每个依赖再用同样的命令去查它们的依赖,递归下去。实际操作中,如果依赖层级很多,纯手动非常痛苦。这个方法适合依赖少、层级浅的小工具类软件,比如只依赖两三个基础库的小命令。

3.2 精准模拟:用apt-get install --simulate拿到完整依赖清单

这个方案是我日常工作用最多的。apt-get install --simulate(简写-s)的作用是模拟安装过程,不实际下载、不安装,只打印apt的解析结果。执行后输出里会有大段以Inst开头的包列表,这些就是apt认为需要安装的所有依赖包。

举个例子,在一台UOS机器上执行:

sudo apt-get install --simulate onlyoffice-desktopeditors

输出会显示类似:

Inst libcurl4 (7.74.0-1.3+deb11u7 amd64) Inst onlyoffice-desktopeditors (7.3.3.131 amd64)

把Inst后面的包名提取出来,就是完整的安装清单。接下来把这些包名逐一带给apt-get download:

apt-get download libcurl4 onlyoffice-desktopeditors

执行完之后你会发现当前目录下多了一批deb文件,这就是离线安装所需的全部家当。

提示:apt-get download只接受包名,不接受deb文件路径。如果你有一个chroot环境或想安装一个本地deb并把它的依赖打包离线,请参考下一节的chroot方案。

3.3 一网打尽:chroot环境下的完整依赖下载

上面两种方案有一个共同局限:它们依赖apt的模拟分析,如果你的目标机没法联网、没法跑apt update,而你又想精准预测某个本地deb文件在干净系统上的依赖,怎么办?

chroot方案能解决这个问题。思路是:在下载机上创建一个小型"模拟目标机",把目标机的系统源和deb包放进去,在chroot环境里运行apt来下载依赖,下载完把deb全部取出。

核心步骤如下:

# 1. 创建一个chroot目录并安装debootstrap(若系统里有UOS的base文件系统,也可以直接用它) sudo debootstrap --arch=amd64 beige /var/chroot/uos-target # 2. 进入chroot并配置UOS的源 sudo chroot /var/chroot/uos-target # 在chroot中写入与目标机一致的source.list,然后执行apt update # 3. 在chroot中模拟安装 apt-get install --simulate <软件包名> # 4. 在chroot中下载所有deb到某个目录 apt-get download $(apt-cache depends --recurse --no-recommends --no-suggests <软件包名> | grep -E '^[a-zA-Z0-9]' | tr '\n' ' ') # 注意:这条命令需要包管理器递归解析,实际使用时最好配合apt-rdepends

看起来有些繁琐,但它的好处是:能在一个与目标机高度一致的软件环境中做依赖解析,不会因为下载机装了一堆额外软件而绕开某些依赖。三种方案的适用场景可以这么区分。

方案适合场景优点缺点
apt-get download手动分析单包小依赖、应急简单直接依赖多时容易漏
apt-get install --simulate常规软件离线打包精准、依赖完整需要在能解析源的环境中执行
chroot环境复杂依赖、不能污染下载机环境最接近目标机真实状态搭建繁琐、占用空间

4. 把反复下载封装成脚本:批量获取依赖与apt-offline方案

4.1 自动提取依赖列表并批量下载的完整脚本

当你需要下载十几个软件包、每个包又有几十个依赖时,手工敲命令就完全不现实了。我已经习惯把整个过程封装成一个bash脚本,核心逻辑是:先用apt-get install --simulate生成依赖清单,解析出所有包名,再循环调用apt-get download批量下载,最后把下载好的deb归档到一个目录里。

下面是一个可直接使用的脚本,在UOS/deepin/Debian系机器上都适用:

#!/bin/bash # uos-debs-download.sh # 用法: ./uos-debs-download.sh <软件包名...> DOWNLOAD_DIR="$HOME/offline-debs" mkdir -p "$DOWNLOAD_DIR" PACKAGES="$@" if [ -z "$PACKAGES" ]; then echo "请至少指定一个软件包名" exit 1 fi # 1. 生成依赖清单(模拟安装输出) SIM_OUTPUT=$(apt-get install --simulate $PACKAGES 2>/dev/null) if [ $? -ne 0 ]; then echo "模拟安装失败,请先确认apt源可用并已执行apt update" exit 1 fi # 2. 提取Inst开头的包名 DEPS=$(echo "$SIM_OUTPUT" | grep '^Inst ' | awk '{print $2}') # 3. 把主包也加入清单 ALL_PACKAGES="$PACKAGES $DEPS" # 4. 逐一下载 cd "$DOWNLOAD_DIR" for PKG in $(echo "$ALL_PACKAGES" | tr ' ' '\n' | sort -u); do if [ -f "${PKG}_"*.deb ] 2>/dev/null; then echo "跳过已存在的 $PKG" continue fi echo "正在下载: $PKG" apt-get download "$PKG" 2>/dev/null || echo "下载失败: $PKG" done echo "全部下载完成,文件保存在 $DOWNLOAD_DIR" ls -lh "$DOWNLOAD_DIR"

脚本里有两个值得注意的细节:

  • sort -u去重:同一个依赖可能被多个主包共享,没必要重复下载。
  • 已存在文件的跳过判断:如果之前下载过某个包,再次执行脚本时不会覆盖,这能避免反复下载大文件。

4.2 apt-offline:一个更省心的离线工具方案

如果你觉得手动写脚本太麻烦,apt生态里还有一个现成工具叫apt-offline,专治离线环境依赖问题。它的工作方式是在目标机上生成一个需求文件,然后在下载机上按需求文件下载包,最后把包带回目标机安装。

目标机(离线机)上执行:

sudo apt install apt-offline sudo apt-offline set /tmp/offline-request

apt-offline set会根据当前系统已安装的包和差额,生成一个包含所有需要下载包信息的签名文件。把它拷贝到下载机:

sudo apt-offline get /path/to/offline-request -d /path/to/debs-dir

之后把debs-dir里的包拷回目标机,执行:

sudo apt-offline install /path/to/offline-download

它能自动处理包顺序和依赖安装,比纯手动dpkg省心很多。不过要注意:UOS的源里有可能没有预装apt-offline,目标机上如果连这个工具都装不上,可以先用上面的一键脚本把离线包下载完,然后用dpkg -i进行安装。我在实际项目里,两种方案都留下备着:脚本负责批量下载,apt-offline负责精细化增补。

5. 离线安装全链路:组织deb仓库、dpkg安装顺序与修复手段

5.1 构建一个结构清晰的离线仓库目录

下载回来的几十个deb包如果全部堆在一个目录里,一到安装时就会非常乱。我习惯按项目或日期建目录,每个项目单独一个文件夹,里面再细分debs、lists、logs几个子目录。

比如这样一个结构:

/opt/offline-pkgs/ ├── office-debs/ │ ├── debs/ # 所有deb文件 │ ├── install-list.txt # 从simulate输出的包清单 │ └── install.log # 安装日志 └── dev-tools/ ├── debs/ ├── install-list.txt └── install.log

目录建好之后,建议在正式安装前用dpkg-deb -I检查一下主包的Depends字段,和目录里的deb文件对照一遍,看缺没缺依赖。这一步虽然多花几分钟,但能避免在目标机上装到一半才发现缺包。

5.2 安装策略与常用dpkg参数

内网安装时,最直接的方式是dpkg -i。但如果依赖顺序不对,报错几乎是必然的。我的经验是分三步走:

第一步,先安装基础依赖库,再把主包放最后。可以按依赖树从底向上装,但人工排序在大包面前不现实。一个更聪明的做法是:先把所有deb包丢给dpkg装,让它自己报错,然后用dpkg --fix-broken自动修复依赖问题。

cd debs sudo dpkg -i *.deb sudo apt-get install -f -y # 或者使用 dpkg --fix-broken

dpkg -i *.deb会按文件名顺序尝试安装,中途如果遇到未满足的依赖,会中断并提示。这时执行apt-get install -f,它会尝试修复依赖关系——在离线无源的情况下,修复能力取决于你已经放进去的deb是否覆盖了缺口。

第二步,如果依赖缺口较多,修复无果,就得找到具体缺哪个包,从离线包里补装:

sudo dpkg -i /path/to/missing-package.deb

第三步,安装完成后统一配置:

sudo dpkg --configure -a

这个命令会把所有已解包但未配置的包做一遍配置,经常在安装中断后使用,能回收不少半成品状态。

5.3 安装验证与半配置状态修复

装完之后别急着撤,至少用下面几个命令确认一次:

# 查看主包是否正常安装 dpkg -l | grep <包名关键字> # 查看某个关键动态库是否能被系统找到 ldconfig -p | grep <库名> # 查看程序的依赖是否全部满足 ldd /opt/<程序路径>/<可执行文件>

如果dpkg -l里状态显示ii,表示安装成功;如果是iU、iF这类状态,说明包已解压但未配置或配置失败,需要执行dpkg --configure -a再次修复。我在一次批量部署WPS时遇到过iF状态,直接重新执行dpkg --configure -a就恢复了,问题不大。

6. UOS离线部署的高频坑,以及把离线包变成内网apt源

6.1 不能直接剪切粘贴安装目录的软件:注册机制的坑

UOS环境里有一类常见误解:以为把一台机器上装好的软件目录(比如/opt/xxx)直接拷贝到另一台机器上,就能正常使用。实话说,这对于一些绿色软件可能行得通,但对office、wps这类深度集成的办公软件,绝对不行。

原因是这些软件在安装过程中会做大量系统级注册:

  • 写入动态库缓存和系统路径:比如/usr/lib下的库链接,缺了它,程序根本起不来。
  • 在/etc、~/.config等位置保存配置和注册信息,软件启动时会校验。
  • 注册菜单项、文件关联、图标主题、字体缓存等桌面环境资源。
  • 部分软件使用了账号或授权文件绑定机器信息,直接拷贝授权失效。

所以无论离线包多大,也要用deb包正规安装。如果实在找不到deb包,只能拷贝目录,那也要把上面这些系统级配置一并迁移,操作成本比重新安装高得多。

6.2 多版本依赖冲突与锁定策略

离线安装时,最怕的是两个软件对同一个依赖库的版本要求互相冲突:A要libfoo-1.0,B要libfoo-2.0,而系统只能装一个。在线环境下apt会自动做一些妥协或提示冲突,离线手工安装时这个矛盾会直接摆到你面前。

我的处理思路是:能用系统自带版本就优先用系统自带版本;如果某个软件必须升级共享库,我会先确认升级后其他软件会不会受影响。在部署时,尽量保持系统base环境版本和下载离线包时一致,不轻易手动升级核心库。对于确实要锁定版本的包,可以在源里用apt-mark hold把自己不希望的升级包锁住:

sudo apt-mark hold libfoo

这样后续即使有源、有人手贱跑了apt upgrade,libfoo也不会被意外升级。

6.3 把离线仓库变成内网apt源:一劳永逸的做法

如果你的项目不止一两台机器,而是几十台上百台,逐台dpkg装包就是灾难。更好的方案是把离线deb包整理成一个内网apt源,让所有内网机器像在线环境一样使用apt install。

核心原理是apt源本质上就是一个目录加一个Packages索引文件。用apt-ftparchive可以快速生成索引:

# 把所有deb放进同一目录,如/var/www/uos-repo/debs cd /var/www/uos-repo dpkg-scanpackages debs /dev/null | gzip > debs/Packages.gz

然后配置内网机器的源,指向这台仓库服务器:

deb [trusted=yes] http://192.168.1.100/uos-repo/debs/ beige main

配置完成后执行apt update,apt就能看到这个离线源里的所有包,依赖解析也恢复在线一样的体验。这个方案我一向推荐给长期项目使用,因为它把"离线"转变成了"受限在线",后续任何一台机器缺包,直接从内网源装,完全不需要再碰U盘。

如果觉得dpkg-scanpackages在UOS里没有预装,可以改用apt-ftparchive packages . > Packages,效果类似。

最后再分享一点实操心法

做了这么多UOS离线部署之后,我最大的体会是:离线部署本身不难,难的是版本一致性和流程标准化。下载离线包的机器,尽量保持和目标机同系统版本;每次下载完的deb包,不要直接扔进U盘,先归档、记录清单、写清日期和对应源环境;一套完整的离线包,务必要在测试机上从零装一遍验证,确认没问题再送去现场。

一个小技巧是:下载完离线包之后,顺手在下载目录里生成一个manifest.txt,把每个deb包的文件名和版本号都记下来。真到了现场发现少了一个包,查这个文件就能知道当时是从哪个源、哪个版本环境下载的,排查效率翻倍。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询