ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

麒麟系统离线部署指南:在线提取依赖包,目标机本地源安装

麒麟系统离线部署指南:在线提取依赖包,目标机本地源安装 做麒麟系统项目一年多我遇到最多的一个部署场景就是开发机上软件装得好好的一到了目标机上就抓瞎——要么没网要么网络策略限制软件源只能眼巴巴看着。最开始我都是拿着U盘到处找deb包后来索性琢磨出一套完整的“在线安装、提取离线包、目标机离线部署”流程帮团队省了不知道多少加班时间。这篇笔记就把这套流程完整拆开讲适合所有做麒麟系统开发、实施、运维的朋友直接照着抄。先说清楚这套方法能解决什么问题你有两台或一批麒麟系统的机器开发环境能联网目标环境不能联网。你需要在开发机上把某个软件装上、调明白然后把软件连同它所有依赖一起提取出来搬到目标机上装好。这个需求在保密网、内网机房、生产环境里太常见了。文章的核心关键词就是“在线安装”“安装包提取”“离线软件包”“离线安装”整条链路我全部跑通过所以把关键步骤、踩过的坑、排查思路一次性写给你。1. 场景与目标为什么要“在线装完再提取离线包”1.1 需求来源与适用边界我在项目里遇到的实际场景是开发阶段用的是麒麟桌面版连的是公司测试网apt源都通着装什么软件都方便。但项目落地时发现目标机所在的业务网络是隔离的USB接口管理也很严更别说访问外部仓库了。这时候能提前在开发机上把软件环境完全跑通再把可离线安装的软件包带过去就成了唯一现实可行的交付路径。这个需求适用范围其实很宽。不只是麒麟系统像CentOS、Ubuntu、统信UOS这类基于Debian或RPM体系的Linux系统都有类似问题。但对于国产发行版还有个额外的特殊性——它底下的组件版本、内核、glibc版本可能和上游不一样所以不能完全照抄Ubuntu的做法。凡是“开发机能上网、目标机不能上网”的项目这套方法都适用凡是目标机和开发机是同版本、同架构离线安装的成功率会非常高。1.2 三种主流方案对比先看结论再决定用哪种我最初以为提取离线包只有一种做法实际做下来发现至少有三种适合的场景差异很大。直接上结论后面再逐一拆解。方案核心命令适合场景优点缺点A. 缓存回收从/var/cache/apt/archives/拷出deb刚装完软件缓存还没被清理最快零成本缓存可能已被清理不包含安装期间修改的配置B. 重新打包dpkg-repack 包名软件已装好且配置了重要参数连当前配置一起打包需要先在本机安装dpkg-repack工具C. 依赖清单补包apt download 包名包多依赖复杂需要完整依赖链可控性强能精确把依赖补全需要手动分析依赖关系稍繁琐三个方案不是互斥的。我在实际项目里经常先用方案A把能捡的缓存都捡出来再拿方案C补漏最后拿方案B处理那些带配置的定制软件。先把结论放在这你遇到具体场景就知道该选什么了。1.3 实施前要准备的环境与工具清单在动手之前先确认以下几件事能避免后面走弯路。开发机麒麟系统能联网软件源配置正确最好用root或者具备sudo权限的账号操作。目标机麒麟系统版本号和内核架构尽量与开发机一致。比如都是银河麒麟V10 SP1 x86_64这样提取出来的包才不会出现系统版本依赖问题。传输介质U盘、移动硬盘或者内网共享目录都可以。注意如果介质格式是FAT32单个文件不能超过4GBdeb包一般没这么大但累计多了也有拷贝失败的情况建议直接用exFAT或者ext4格式。基础工具dpkg-dev、dpkg-repack、apt-utils这些在开发机上提前装好。工具本身也要走apt install既然开发机能联网先把准备工作做足。确认完这几点就可以进入下一节理解离线包的底层逻辑了。2. 包管理机制与离线包的底层逻辑2.1 麒麟系统如何管理软件包apt/dpkg体系麒麟系统的软件管理沿用了Debian系的优秀设计底层是dpkg负责真正地安装、卸载、查询单个deb包上层是apt负责从软件源拉取包、解析依赖关系、处理安装顺序。用生活类比来理解dpkg就像仓库里的搬运工你告诉他“把这个箱子搬到3号货架”他只会搬运不思考这个箱子是不是和别的箱子冲突。apt则像个调度员他知道仓库里所有箱子的货位和依赖关系他会告诉你“你要的箱子需要先搬A箱和B箱而且A箱和B箱又依赖C箱所以我要按顺序把C、A、B、你要的箱子依次搬过去”。理解这个分工很重要因为离线包提取和安装的核心难点恰恰是**“没有调度员”**。当你把一堆deb包拷到目标机上用dpkg -i逐个安装时相当于让仓库里的搬运工“盲装”——他不理解依赖只管一个个往上搬。只有把你提取的包都放进本地apt源重建“调度员”之后apt才能像在线环境一样自动处理依赖。2.2 一个deb包内部到底装了什么deb包本质上是一个ar格式的压缩归档文件里面包含三个部分debian-binary版本标识文件、control.tar.xz控制信息里面含依赖关系、安装脚本、包描述、data.tar.xz实际文件内容也就是程序本体要安装到的路径。我刚开始时以为只要把deb拷过去就能装后来才发现一个坑deb的依赖关系写在control文件里而不是程序运行时才去检查。如果你只拷了程序本体那个deb没拷它依赖的那些deb用dpkg -i安装时会直接报错“依赖关系未满足”有时候甚至会把系统搞坏。举个例子装一个Qt开发环境核心包可能只有几百兆但它依赖的库、编译器、构建工具加起来能到一两个GB。你想省事只带核心包结果目标机上库版本全对不上。所以我后面总结出一条铁律提取离线包必须把依赖链完整提取出来不只是装目标软件本身。2.3 离线迁移最难的是“依赖链”而不是单个包做离线部署时间长了就会发现真正的难点不是把软件本体带过去而是把和它相关的“依赖网”一起搬过去。在在线环境里apt会自动帮你解析依赖你可能感觉不到这个问题一旦断网所有问题都会暴露出来。依赖链上最常见的坑有三类。第一类是跨系统库的版本冲突软件A依赖libssl1.1软件B依赖libssl3两个装完可能把系统的SSL库搞乱第二类是安装脚本里的“隐式联网”有些包的postinst脚本会在安装时自动下载字体、插件或更新索引断网情况下会卡死或者失败第三类是脚本里依赖了某个命令或服务比如包安装时要用update-alternatives、ldconfig这类工具但目标机上缺少这些工具。理解了这几层再看后面的实操命令就不会觉得我总在强调“别忘了依赖”“记得验证”是啰嗦了。这些都踩过坑才总结出来的。3. 在线环境提取安装包三种可行方法全流程3.1 方法A缓存区直接回收适合刚装完软件的场景apt在线安装时下载的deb文件都会先落到/var/cache/apt/archives/目录里安装成功之后这些文件默认会保留。所以如果你刚在开发机上用apt install装完软件第一件事就是去看这个目录。# 查看当前缓存的deb文件 ls -lh /var/cache/apt/archives/ # 按修改时间从近到远查看找到刚安装的包 ls -lt /var/cache/apt/archives/ | head -20 # 把目录里所有deb先拷贝到工作目录 mkdir -p ~/offline_packages cp /var/cache/apt/archives/*.deb ~/offline_packages/这里有几个注意点。一是不要忘了检查locked或partial子目录apt下载到一半的文件会放在partial/目录如果下载还没完成就中断了那边会有不完整的deb二是拷贝前先跑一次apt clean之外的检查我自己喜欢先看下deb包的完整性用dpkg-deb -I快速读一个包的control信息能正常读出来就说明文件是完整的。# 校验包文件完整性能输出包信息说明文件有效 dpkg-deb -I ~/offline_packages/你的软件包.deb | head -20方法A最快的场景是你装完软件后马上提取还没执行过自动清理。如果缓存被清了别慌跳到方法B或者方法C。3.2 方法B用dpkg-repack重新打包已装软件和配置一起带走项目里有个常见需求软件装完后调了很多配置想把这套“调好状态”原样搬到目标机上。这时候直接用源码deb包不够因为配置文件不一定在里面。dpkg-repack就是为此设计的它会把系统里已经安装的软件包连当前配置文件一起重新打成一个deb。# 第一步安装dpkg-repack工具开发机能联网这一步很轻松 sudo apt install -y dpkg-repack # 第二步查询已安装软件的确切包名 dpkg -l | grep 你的软件关键词 # 第三步重新打包 dpkg-repack 包名执行完会在当前目录生成一个类似软件名_版本号_架构.deb的文件。这个包的特别之处在于它不只是把程序文件打包还会把目标机器上对应的配置文件、目录权限、状态也打包进去。在调优过数据库参数、中间件配置的场景下特别好用。我用这个命令打过一个内网用的小型应用服务开发机上把数据目录、日志切割策略、启动参数全部调好了用dpkg-repack打包搬到目标机上装完基本不用进一步配置直接就能启动服务。但也要注意dpkg-repack并不是万能的。如果你在安装软件后又手动编译安装了某个库或者直接改写了软件安装目录下的文件这些内容并不会被包含进deb包。所以这个方案只适合“通过包管理器安装且配置存在标准路径”的场景。3.3 方法C按依赖清单用apt download补全完整构建依赖链真正复杂的项目依赖关系会像树一样展开。这个时候靠缓存和重打包都不够最可靠的方式就是显式列出依赖清单逐个下载。我通常用这个流程来构建完整依赖包# 1. 查看目标软件包的依赖关系 apt depends 软件包名 # 2. 查看更细的依赖信息包括推荐/建议 apt-cache depends 软件包名 # 3. 递归查找依赖树 apt-cache depends --recurse --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances 软件包名第三步的输出会递归展开所有依赖包名。拿到这个清单后写个小脚本统一用apt download下载# 把依赖清单存到文件里 apt-cache depends --recurse --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances 软件名 depend_list.txt # 从清单中提取包名逐个下载 cat depend_list.txt | grep -E ^[a-zA-Z0-9] | sort -u | while read pkg; do apt download $pkg 2/dev/null done # 把目标包也下载到同一目录 apt download 软件包名apt download只下载不安装文件会直接落到当前目录。跑完一轮检查一下目录里的deb数量如果依赖本身还有“推荐安装”的额外包没被--no-recommends过滤掉可以个别再补。这个方法最稳但有个明显的代价耗时较长而且可能下载出几十个甚至上百个包。我之前部署一个带web界面的监控工具依赖链走完拉下来八十多个deb打包压缩后接近300MB。一开始觉得畸形但后来发现这恰恰是“最全”的方案目标机上安装基本没有意外。3.4 提取后的传输准备压缩、校验、归档提取完的deb目录可能很乱文件名也很长。在传到目标机之前我习惯先整理成固定结构并做一个清单文件方便目标机上核对。cd ~/offline_packages # 生成清单记录所有包名和校验值 dpkg-scanpackages . /dev/null | grep -E ^(Package|Version|Filename): manifest.txt # 或者直接用md5sum生成文件指纹 md5sum *.deb md5sums.txt # 打包方便拷贝 tar -czf offline_packages.tar.gz .这里有个很实用的小经验把所有deb和md5校验文件放在同一个tar包里传到目标机上先跑一遍md5校验防止U盘拷贝过程中出现文件损坏。deb包在文件传输中虽然出错的概率不高但一次“第3个包校验不过”的报错就能让你从头排查是否拷贝完整特别浪费时间。另外如果deb包数量多尽量把目录名改成有意义的比如20240511-offline-mysql-client后面使用时不容易混淆。4. 目标机离线安装从手动装到本地软件源4.1 快速方案按依赖顺序用dpkg -i手动安装如果你提取的包数量很少比如三五个或者你完全掌握了依赖顺序最直接的方式就是用dpkg -i手动安装。# 先安装依赖包再安装主包 sudo dpkg -i 依赖1.deb 依赖2.deb 主包.deb # 或者进入deb目录一条命令装所有 sudo dpkg -i *.deb但这里有个大坑*dpkg -i.deb 不是万能的。如果依赖有顺序要求或者安装过程中某个包的postinst脚本报错后面package的操作可能全部受影响。更麻烦的是dpkg -i安装产生的依赖缺失不会自动去网上找装完你还需要检查状态。所以在手动安装时我强烈建议装上几个辅助工具再动手# 修复不完全状态 sudo apt --fix-broken install # 查看是否有依赖问题 sudo apt check如果是在断网环境下apt --fix-broken install可能会尝试连接软件源而卡住这时候要加个参数# 仅修复dpkg状态不联网查询新包 sudo dpkg --configure -a手动安装适合小而精的场景。一旦依赖超过十个强烈建议用下面的本地仓库方案。4.2 规范方案构建本地apt仓库apt自动解析依赖解决离线安装最优雅的思路就是把提取出来的deb包做成一个本地apt源。你只需要在目标机上建一个目录把所有deb放进去用工具生成索引再把软件源指向本地这样apt就能像在线环境一样处理依赖和安装顺序。执行步骤也不复杂# 1. 在目标机上创建目录把deb包都拷贝进去 sudo mkdir -p /opt/offline-pkgs sudo cp -r ~/offline_packages/*.deb /opt/offline-pkgs/ # 2. 安装dpkg-dev如果目标机已安装可跳过 sudo apt install -y dpkg-dev # 3. 扫描目录生成Packages索引 cd /opt/offline-pkgs sudo dpkg-scanpackages . /dev/null | gzip Packages.gz然后配置apt源。不同麒麟版本的源配置文件路径可能有差异一般在/etc/apt/sources.list或者/etc/apt/sources.list.d/目录下。可以在/etc/apt/sources.list.d/新增一个本地源文件# 编辑新增的本地源文件 sudo vi /etc/apt/sources.list.d/offline.list # 文件内容trustedyes表示信任该本地源 deb [trustedyes] file:/opt/offline-pkgs ./然后更新并安装sudo apt update sudo apt install -y 软件包名这个方案的好处在于apt会在本地目录里自动解析依赖装错了顺序也没关系它会自己找到合适顺序。另外因为你提取的包足够完整依赖缺失的概率会被压到最低。我建议无论包多包少都在目标机上搭这个本地仓库一次搭建后面反复使用。在项目里我甚至把本地源直接做成了脚本目标机拿到离线包后一键生成源、一键安装实施时间从原来的40多分钟压缩到5分钟。4.3 装完之后的验证不是“装上了”就算完离线安装最怕的陷阱是命令执行完没报错但你实际运行程序时却发现缺库、缺配置甚至程序起不来。所以验证环节一定要做全。# 1. 确认包状态为 ii正常安装 dpkg -l | grep 软件名 # 2. 查看软件实际安装路径 dpkg -L 软件名 | head -20 # 3. 验证动态库依赖是否完整针对可执行程序 ldd /usr/bin/你的软件命令 # 4. 直接启动程序测试 你的软件命令 --version其中ldd这个命令特别值得注意它会把可执行文件依赖的所有动态库列出来如果输出里出现“not found”那说明即使deb包状态正常程序也跑不了。这种情况多半是依赖链里还漏了某个运行库回到开发机上用apt download把它补下来再走一轮本地源安装即可。5. 高频问题与排查技巧记录5.1 依赖错误Version xxx was not found 或 depends on xxx but it is not installable这是离线安装最常见的问题报错信息翻译成人话就是你手里的包和系统里已有的包版本对不上。原因多半是开发机和目标机的软件源版本有差异开发机装的是新版依赖库目标机源或系统里只有旧版。排查思路是先看报错里提到的包名回到开发机上查它当前版本apt-cache policy 依赖包名如果目标机上能装这个版本单独下载对应完整版本再装如果目标机系统里完全找不到就要把这个依赖包连同它的依赖一起补到本地源里。这个坑很难一次性避免但我有一个经验尽量保证开发机和目标机用同一个版本的系统镜像和同一套软件源配置。版本差得越小离线安装越顺。5.2 架构或系统版本不匹配wrong architecture 或 cannot be installed提取离线包之前一定要确认CPU架构一致。麒麟系统常见的有amd64x86_64、arm64aarch64、mips64el等架构一种是dpkg --print-architecture查当前架构一种是看deb包文件名里的架构字段。如果不匹配dpkg -i会直接报错“wrong architecture”。还有一个容易被忽略的点是系统版本差异。银河麒麟服务器版和桌面版、V10和V10 SP1之间底层库版本都可能不同。最好的做法是在和目标机同批次、同版本的系统上提取离线包如果做不到安装前先对比一下两边的关键系统库版本dpkg -l | grep -E libc6|libssl|libstdc\\\\5.3 安装脚本或后置资源需要联网有些软件在安装过程中会主动联网下载资源比如装一个带Web管理界面的工具时postinst脚本可能尝试拉取Node.js依赖、下载字体或更新CA证书。在断网状态下这个脚本可能会卡住几分钟之后超时报错。我在实践中的处理方式是# 手动下载脚本需要的资源放到对应路径 # 或者直接安装时跳过某些挂载在联网阶段的步骤用环境变量控制 sudo DEBIAN_FRONTENDnoninteractive apt install -y 软件包名必要时可以先把deb包解包看看它的postinst脚本做了什么判断它是否会联网。比如用dpkg-deb -e 包名解出control部分然后检查postinst文件内容。虽然麻烦但遇到疑难杂症时很有效。5.4 离线源配置后 apt update 报错配置本地源后apt update报错通常有两种情况一是Packages.gz没有生成或者路径写错二是源配置文件里路径写错了。排查时先确认三个点# 目录存在且里面有deb ls /opt/offline-pkgs/*.deb # Packages.gz存在 ls -lah /opt/offline-pkgs/Packages.gz # 源路径正确注意最后是 ./ cat /etc/apt/sources.list.d/offline.list还有一点用了file:/本地源之后尽量把在线源临时清理或注释掉免得apt update时因为连不上外网而等待很长时间。不过有的项目目标机是内网隔离的源里只有本地源那就没这个问题。5.5 排查命令速查表离线安装问题优先用这几个我把平时排查离线安装问题用得最多的命令整理成了一张速查表出现异常先按这个顺序过一遍。问题现象排查命令关注点装不上提示依赖未满足apt-cache depends 包名/dpkg -s 依赖包名对照依赖清单查缺的包能装上但程序启动失败ldd 可执行文件路径关注not found的库包状态显示异常dpkg -l 包名出现iU、iF等状态需要dpkg --configure -a系统被装乱想回滚dpkg -r 包名从后往前卸载留意依赖关系本地源不生效apt update后看Sources输出确认源路径、Packages.gz是否生成文件拷贝损坏md5sum -c md5sums.txt在目标机比对全部deb指纹写在最后我从一开始把deb往U盘一塞就直奔目标机到现在把整套离线包流程拆成脚本化、标准化操作中间踩过不少坑。现在做离线部署时最典型的成功路径是这样开发机上先用apt-cache depends --recurse生成依赖清单用apt download把包全部拉下来同时用dpkg-repack处理带配置的定制软件再在目标机上搭一个本地apt源最后用ldd和启动测试双重验证。整个过程已经稳定跑了很多台机器。有一个额外的小技巧忍不住分享做完离线包之后我会在源目录里额外放一个README.txt写清楚这批包是什么版本、什么时间、在什么系统上提取的。等到几个月后你看着几十个deb文件发懵的时候这个文件能救你一命。
返回列表