ARTICLE DETAIL

资讯详情

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

openEuler Embedded新增软件包:离线与在线安装全流程实战

openEuler Embedded新增软件包:离线与在线安装全流程实战 做嵌入式Linux开发的人十有八九都被“装个软件”这件事恶心过。通用Linux上一条dnf install就能解决的事在嵌入式板子上经常变成一场灾难。我最近在 openEuler Embedded 上折腾新增软件包把在线安装和离线安装的路子都试了一遍踩了不少坑也把真正能跑通的流程梳理了出来。这篇文章就专门聊聊 openEuler Embedded 新增软件包和在线安装软件这件事适合正在用或者准备用 openEuler Embedded 做产品开发的工程师参考尤其适合那些被“无法定位软件包”“软件包似乎无效”这类报错折磨过的朋友。先说结论openEuler Embedded 和普通 Linux 发行版的包管理思路差异很大你没法把它当成 mini 版 CentOS 来用。镜像默认做了大量裁剪很多通用发行版自带的工具在这里不存在软件源也不像服务器版那么全。想“新增软件包”你得先搞清楚系统当前的架构、版本、包管理工具状态再决定走“离线 RPM”“本地源”还是“在线 dnf”哪条路。这篇文章会把每条路线的原理、步骤、坑点一次讲透。1. 先搞清楚问题出在哪openEuler Embedded 的包管理背景1.1 它和通用 Linux 最大的区别裁剪、只读、架构差异openEuler Embedded 是面向嵌入式场景的发行版虽然继承了 openEuler 的 RPM 体系但它和服务器版、桌面版完全是两回事。嵌入式系统为了控制镜像体积、减少攻击面、保证启动速度rootfs 通常是深度裁剪过的很多命令、库、工具链都不会预装。你和通用 Linux 的习惯性操作在这里要么找不到命令要么能跑但一运行就缺库。比裁剪更麻烦的是只读文件系统。不少 openEuler Embedded 镜像是把根文件系统做成只读或者 overlayfs 的形态你辛辛苦苦装好一个软件重启之后发现“回到了解放前”。这不是软件包本身有问题而是系统的存储布局设计成“重启还原”你得先搞清楚/的挂载方式再决定怎么持久化安装结果。另外还有架构差异。开发机绝大多数是 x86_64而 openEuler Embedded 的常见目标平台是 aarch64ARM64和 riscv64。你在 x86 服务器上dnf install习惯了拿到板子上手就装十有八九会碰上“架构不匹配”的报错。这不是软件不存在而是你选的包根本不是这个 CPU 能跑的。1.2 包管理工具链现状rpm、dnf 可能都不完整openEuler Embedded 继承了 openEuler 的 RPM 体系但“继承”不等于“完整”。我实际遇到的情况是镜像里rpm命令经常是有的但dnf不一定带yum基本别指望。这就带来一个很现实的问题——rpm本身不会自动解析依赖没有dnf就缺少“在线安装”的通道。登录板子之后我建议你立刻跑下面三组命令把家底摸清楚which rpm dnf yum ls /etc/yum.repos.d/ 2/dev/null || ls /etc/dnf/ 2/dev/null cat /etc/os-release如果which输出里只有 rpm没有 dnf那你别急着想在线安装先把“离线 RPM”和“构建新包”这两条路走通。如果 dnf 也在那后面的在线源方案才真正有戏。无论哪条路都要先确认系统大版本因为官方源是按openEuler-22.03-LTS、openEuler-23.09这类版本组织目录的。1.3 新增软件包的四种路径先看清再动手我把 openEuler Embedded 上新增软件包的方法总结为四条路径你可以按实际环境选路径适用场景依赖处理复杂度离线 RPM 安装临时应急、网络隔离、包数量少手动处理或提前拉取依赖低本地 repo 源伪在线内网批量部署、多台板子配置 dnf 自动解析中在线 repo 源dnf install能访问外网、官方源有现成包dnf 自动解析中SDK/bitbake 构建官方源没有、需要自定义编译构建时自动处理高这个表格是我实际选型的心得。很多人一上来就想“在线安装”结果发现源里没有想要的包也有很多人喜欢直接rpm -ivh硬刚结果被依赖折磨到怀疑人生。正确的思路是先看官方源里有没有有就尽量用 dnf 在线装没有但有现成 rpm就离线装都没有老老实实去构建系统里现造一个。下面我把每条路径逐一展开。2. 准备工作确认环境、锁对软件包来源2.1 登录板子后第一时间要跑的检查命令不要一拿到板子就想着装软件先花两分钟做环境体检。我每次拿到新板子都会固定执行一套命令后面能少踩一半的坑。uname -m # 查看 CPU 架构找对 rpm 包 cat /etc/os-release # 查看系统大版本决定用哪个源 df -h / # 确认根分区剩余空间 cat /proc/mounts | grep / # 看根文件系统是不是只读/overlay free -m # 确认内存足够避免大软件装完运行直接 OOM为什么要看前两个因为嵌入式镜像的架构和版本决定了你所有后续动作。如果你在 aarch64 的板子上装了一个 x86_64 的 rpmrpm -ivh可能会直接拒绝也可能装进去之后一运行就是Exec format error。版本不匹配更隐蔽装进去大概率碰到.so版本冲突查起来非常费劲。至于第三、四条是我吃过亏之后才养成的习惯。有块板子的根分区只有 400MB缓存一满dnf install装到一半就报磁盘空间不足还把系统搞到半残。遇到这种板子优先清理dnf clean all或者先把软件包下到内存挂载点、确认能装再往系统里放。2.2 openEuler Embedded 的软件仓库长什么样openEuler Embedded 的软件包并不是随便找个 openEuler 源就能装的。官方把嵌入式场景的软件包单独放在了 repo.openeuler.org 站点下结构上通常按“大版本 / embedded_apps / 架构 / Packages”这样的路径组织。比如 22.03 LTS 的 aarch64 嵌入式软件源路径大概长这样http://repo.openeuler.org/openEuler-22.03-LTS/embedded_apps/aarch64/注意版本号一定要和板子cat /etc/os-release里看到的大版本对齐架构目录也要选对。这里有个特别容易犯的错误看到 openEuler 官方源里有很多包就把标准服务器版的 repo 配到嵌入式板子上。这通常不是你想要的因为服务器版软件的依赖链路和嵌入式裁剪版不一致装了很容易把系统搞坏。嵌入式专用仓库里的包是为裁剪环境重新处理过的依赖相对干净针对目标架构尤其是 aarch64 和 riscv64也有现成的编译产物。所以在开始之前去 repo.openeuler.org 看一眼有没有和你系统版本、架构完全匹配的 embedded 目录这决定你后面是“直接在线装”还是“离线下载”。2.3 下载软件包前必须确认的三个元信息不管走哪条路你在下载/安装一个 rpm 之前都要先看三个东西架构Arch、版本Version、依赖Requires。架构通过uname -m确认aarch64 对应 ARM64riscv64 对应 RISC-V别下载错。版本尽量匹配系统大版本比如系统是 22.03 LTS就优先找 22.03 系列的包。依赖用rpm -qpR查看这个包依赖哪些.so和子包提前把依赖链拉齐。如果你手头已经有一个 rpm 文件在没安装之前就能这样检查rpm -qip xxx.rpm # 查看基本信息和架构 rpm -qpR xxx.rpm # 查看依赖列表 rpm -qp --scripts xxx.rpm # 查看安装前/后脚本这个尤其重要--scripts是我强烈推荐你养成的习惯。嵌入式系统裁剪很狠rpm脚本里常用的useradd、install、ldconfig等命令不一定存在脚本一旦失败安装就会报“post-installation 脚本 子进程返回错误状态”之类的错误。提前看一眼能预判很多问题。3. 实操一离线 RPM 安装——最直接但也最容易翻车3.1 下载 rpm 包的几种姿势如果你确定系统里暂时没有可用的在线源只能靠离线 rpm那第一步是找包。我按优先级列出几种方式官方 repo 站点手动下载打开 repo.openeuler.org 对应版本和架构的 embedded_apps 目录按名字找包wget下载。在板子上用 dnf 拉包如果板子上有 dnf哪怕还没配好源也可以在后文配好源之后执行dnf install --downloadonly --downloaddir/tmp xxx把包和依赖一起拉到本地目录。在开发机上用 repoquery 检查依赖如果开发机是 openEuler/CentOS 系列可以安装dnf-utils或createrepo_c相关工具配合仓库查询依赖。这里有个典型错误只下载主包不下载依赖。rpm -ivh时系统会告诉你缺哪个.so你再去下一个包装完又告诉你缺另一个库一层套一层最后“补依赖补到怀疑人生”。正确做法是下载之前先用rpm -qpR把依赖列清楚一次性把需要的 rpm 都找齐。3.2 rpm -ivh 之前先给你的包做“体检”把 rpm 通过scp、U 盘、TFTP 等方式传到板子后不要着急安装。先执行一遍我在 2.3 节说的检查命令确认架构、版本、依赖、脚本都正常。一切 OK 之后再正式安装rpm -ivh tree-2.0.0-1.aarch64.rpm安装完成后用这三条命令确认状态rpm -q tree # 查询是否安装成功 rpm -ql tree # 查看文件都装到了哪里 which tree tree /tmp # 实际跑一下验证二进制能否正常工作很多人在rpm -q显示已安装后就不管了结果一执行就报error while loading shared libraries。这说明依赖库缺失rpm安装本身没问题但运行环境不完整。判断“有没有装上”和“能不能用”是两码事。3.3 大坑依赖问题的三种处理原则依赖问题离线安装中避不开我总结出三条处理原则第一能一次性把依赖都下载齐就别裸着用rpm。第二必须--nodeps时装完后立刻用ldconfig -v检查动态库情况缺库赶紧补。第三永远不要在嵌入式系统里用--force强行覆盖核心包比如 glibc、openssl、systemd 这一类一旦覆盖shell 可能当场崩掉甚至板子直接起不来。如果你实在找不到某个依赖可以用rpm -qpR看一下它具体依赖哪个库文件再去 openEuler 源里搜索对应库的 rpm。比如报缺少libcrypto.so.3()那大概率需要补装openssl-libs或对应版本包。这种“按库找包”的思路在嵌入式环境里比按软件名找包可靠得多。4. 实操二配置本地源实现“伪在线”安装4.1 在服务器上建本地仓库一步到位离线 RPM 装几个包还行如果板上要装十几个软件、依赖关系错综复杂手动处理依赖会痛不欲生。这时候我推荐搭建一个本地 repo 源让 dnf 像在线源一样自动解析依赖。做法很简单。在一台 Linux 服务器上建目录把需要的 rpm 全部放进来然后执行mkdir -p /srv/rpm/openeuler-embedded cp *.rpm /srv/rpm/openeuler-embedded/ cd /srv/rpm/openeuler-embedded createrepo .如果服务器上没有createrepo命令在 openEuler 系列系统上可以用dnf install createrepo_c安装本质一样。执行完会生成一个repodata目录这就是 dnf 识别仓库的依据。4.2 板子上写 repo 文件把源指过来仓库建好之后把整个目录通过 NFS、HTTP 或直接拷贝的方式让板子能访问到。最简单的是在板子上写一个 repo 文件mkdir -p /etc/yum.repos.d cat /etc/yum.repos.d/openeuler-embedded.repo EOF [embedded-local] nameopenEuler Embedded Local Repo baseurlfile:///srv/rpm/openeuler-embedded enabled1 gpgcheck0 EOF如果板子和服务器在同一内网也可以用 HTTP 方式nginx 或python3 -m http.server起一个静态服务baseurl写成http://服务器IP:8000。关键在于gpgcheck0本地源通常没有对应的公钥先保证能装上签名校验等生产环境再严格处理。配好之后在板子上执行dnf clean all dnf makecache dnf list available | head能看到包列表说明本地源已经生效。之后你就可以像在线安装一样执行dnf install xxx了。4.3 为什么说本地源在嵌入式环境里最实用我实际部署过几十块板子深有体会很多嵌入式项目根本不允许设备连接公网所以“在线源”方案在这种环境里就是个摆设。但你又不能靠逐个rpm -ivh装几十个包依赖问题会写到崩溃。本地源正好卡在两者中间从有网络的机器上把官方仓库的嵌入式软件目录整个同步下来或者只同步你要的几十个包然后在隔离内网里搭一个包服务器所有板子统一配这个源。维护起来也很顺手新包只要丢到仓库目录、重新createrepo板子上dnf update就能看到。注意本地源方案的前提是板子上有dnf。如果镜像连 dnf 都没有优先考虑用 SDK 构建一个带 dnf 的镜像否则本地源对rpm命令帮助有限。5. 实操三配置在线源真正实现 dnf install5.1 找对官方 embedded 仓库地址在线安装是所有方法里体验最好的但前提是选对源。不要随手拿一个 apt 源或者标准 openEuler 源来配必须去官方站点确认嵌入式仓库的实际路径。大版本和架构都要和设备完全对应。以 openEuler 22.03 LTS、aarch64 为例repo 文件可以写成这样cat /etc/yum.repos.d/openeuler-embedded.repo EOF [openeuler-embedded] nameopenEuler Embedded baseurlhttp://repo.openeuler.org/openEuler-22.03-LTS/embedded_apps/aarch64/ enabled1 gpgcheck0 EOF路径里的openEuler-22.03-LTS要和cat /etc/os-release看到的大版本一致aarch64要和uname -m一致。如果你用的是 riscv64 板子目录就要切成riscv64。5.2 板子上配置 repo 并刷新缓存写完之后最关键的一步是清缓存、重建元数据dnf clean all dnf makecache然后验证源是否真的通了dnf list available | grep -i tree如果能搜到tree说明在线源没问题。接下来就可以直接安装dnf install -y tree安装过程如果显示多个依赖包一起被解析、下载、安装就说明源和仓库都工作正常。注意dnf install默认会询问是否确认脚本化部署时一定要加-y。5.3 在线安装成功后的验证和注意事项装完别急着收工按这个顺序验证一遍rpm -q tree tree --version rpm -qa | grep tree如果rpm -q显示已安装但执行tree报缺库说明依赖还是没解决干净。这时候回去看dnf list available是否漏掉了某些依赖子包或者源里是否有版本冲突。还有一点要注意在线源里搜不到某个包很正常不要慌。openEuler Embedded 的软件仓库覆盖面比通用发行版小得多很多桌面级、服务器级软件根本没有嵌入式构建版本。遇到这种情况就直接跳到下一章用 SDK 自己构建。6. 实操四没有现成包从 SDK 构建一个 rpm 出来6.1 进入构建环境找到正确的构建入口在线源、本地源、离线包都不好使的时候说明该自己造轮子了。openEuler Embedded 是基于类似 Yocto 的构建体系来生成镜像和软件包的官方 SDK 里有一套完整的构建环境入口一般是oe-init-build-env脚本source oe-init-build-env进入构建环境后如果你是往镜像里加一个已有 recipe 的包可以编辑conf/local.conf在IMAGE_INSTALL里追加包名然后重新构建镜像。如果是要为某个新软件创建包那就需要写一个.bb格式的 recipe 文件定义源码地址、依赖、安装逻辑这个稍微有点门槛但思路和写PKGBUILD或spec文件是相通的。6.2 bitbake 产出 rpm 并传到板子假设你要构建一个软件包mypkg在构建环境里执行bitbake mypkg构建完成后rpm 产物会输出到类似tmp/deploy/rpm/aarch64/的目录下。找到对应的 rpm 文件传到板子上按照第三章的方法离线安装或者放入本地源让 dnf 统一管理。如果你想跳过“安装到镜像”这一步只想快速在板子上跑某个工具也可以直接配置本地源指向同步下来的deploy/rpm目录这样板子端完全不碰编译只是消费 rpm非常干净。6.3 构建常见坑网络下载、机器配置、依赖不全构建系统确实能“造出”官方源里没有的包但坑也不少。第一源码下载。openEuler Embedded 构建时经常要从上游下载源码包国内外网络状况不稳定的话很容易卡在Fetch failed。建议设置DL_DIR指向一个共享下载缓存目录并预先手动下载好常见源码包。第二内存和磁盘。bitbake 编译大软件很吃资源我遇到过几次 OOM构建进程直接被内核杀掉。建议构建机内存不小于 8GB磁盘剩余空间至少 20GB编译临时目录不要用 tmpfs。第三MACHINE 配置。构建时必须明确目标机器名比如 qemuarm64、raspberrypi4-64不同机器输出的包架构、内核模块都不一样搞错了生成出来的 rpm 板子根本装不上。7. 常见问题与排查技巧实录7.1 “无法定位软件包”的几种真实原因“无法定位软件包”是我收到最多的问题但背后原因五花八门。仓库源没配好baseurl写错了、目录不存在、网络不通dnf makecache都过不去。包名和文件名不一致你要搜的是tree但实际 rpm 文件名是tree-2.0.0-1.aarch64.rpmdnf搜索时用的是包名不是文件名。架构不匹配源里只有aarch64的包板子却是x86_64dnf当然认为没有可用包。仓库缓存太旧源里其实有但dnf元数据没更新先执行dnf clean all dnf makecache。版本不对你配的是 23.09 的源系统是 22.03 LTS依赖关系乱搜索不到很正常。遇到这个问题别急着换源按上面几条逐项排查80% 的“无法定位”都能定位到具体原因。7.2 安装脚本报错、依赖死循环怎么破post-installation 脚本 子进程返回错误状态是嵌入式环境常见问题原因大多是 rpm 包里的脚本调用了系统里不存在的命令或路径。排查方式就是我在 2.3 节说的rpm -qp --scripts提前看脚本内容缺啥命令就补装啥。依赖死循环也比较经典比如 A 依赖 BB 依赖 Arpm单个安装会提示依赖缺失。解决办法有两个# 一起安装两个包rpm 可以同时解析 rpm -ivh A.rpm B.rpm # 或者临时跳过依赖检查装完马上验证可用性 rpm -ivh --nodeps A.rpm--nodeps是双刃剑能用但要用在刀刃上。装完立刻ldd验证二进制不要拖。7.3 常见错误速查表错误现象常见原因解决思路无法定位软件包 / 没有可用软件包源没配、架构不符、包名不对核对 baseurl、uname -mdnf makecache软件包似乎无效rpm 损坏、下载不完整重新下载或用rpm -K校验post-installation 脚本返回错误状态包脚本依赖命令缺失rpm -qp --scripts预检补齐依赖工具依赖不足 / error while loading shared libraries只装了主包依赖链没拉齐用 dnf 在线装或提前下载全部依赖磁盘空间不足嵌入式分区太小dnf clean all必要时扩容根分区Exec format error架构不匹配装了错误的 CPU 架构包用uname -m确认重新下对应架构 rpm这张表是我在几十次踩坑后浓缩出来的基本覆盖了嵌入式软件包安装 80% 以上的报错场景。最后再分享一个经验在 openEuler Embedded 上装软件最忌讳的就是“沿用服务器习惯”。先确认架构、版本、包管理工具、磁盘布局这四件事再选安装路径。官方源有包就配置在线源用 dnf没网络就建本地源源里没有就用 SDK 构建。过程不复杂但顺序错了每一步都会很难受。希望这篇文章能让你少走点弯路。
返回列表