拓冰建站拓冰建站
首页 / 资讯中心 / 正文

RPM包管理完全指南:原理、命令、实战与排错全解析

刚入行做Linux运维那会儿我第一件被安排的任务就是在CentOS上装一个内部软件对方扔过来一个.rpm后缀的安装包说“你把这个装上”。我当时连rpm和yum的区别都没搞明白一路乱敲最后依赖问题缠身硬是把一台测试机搞得半残。后来啃了官方文档、看了无数报错、折腾了好几年生产环境才算是把RPM这个东西用得有点心得了。这篇文章不打算给你念man手册而是想从一个实际干活的人角度把RPM这套东西的底层逻辑、常用命令、实战场景和踩坑经验一次性说透。无论你是刚接触Linux的新手还是已经在用yum/dnf但遇到问题就抓瞎的运维这篇文章应该都能帮你在下次面对.rpm文件时更有底气。内容偏长但每段都是实操里用得上的东西。1. 先搞清楚RPM到底是什么别把它和yum混为一谈很多人习惯把“用yum装软件”和“用rpm装软件”当成一回事其实两者压根不在一个层次。RPM全称Red Hat Package Manager它做的事情非常底层把编译好的二进制文件、配置文件、依赖声明、安装卸载脚本打包进一个.rpm文件里然后在系统上完成安装、升级、卸载、查询、校验这一整套动作。你可以把它理解成一个“软件安装工具箱”它只管把包里的东西放到正确位置并记录到本地数据库里。1.1 RPM包内部装的是什么一个RPM包的内部结构远比“把文件复制到目录”要复杂。你可以用rpm2cpio把包解开来看比如rpm2cpio nginx-1.20.1-10.el9.x86_64.rpm | cpio -t这一句能看到包里的文件清单。通常包含这几类内容可执行文件编译好的二进制放在/usr/bin、/usr/sbin等目录。配置文件比如/etc/nginx/nginx.conf这类文件通常标记为config升级时如果你改过rpm不会直接覆盖而是生成.rpmnew文件。动态链接库如.so文件会被安装到/usr/lib64。文档文件帮助手册、README等放在/usr/share/doc。安装脚本比如安装前后需要创建系统用户、启动服务、更新缓存等操作分别记录在%pre、%post、%preun、%postun里。了解这个结构有什么用最大的用处是排查问题。比如你装了一个包但找不到它的配置文件在哪就可以先解开看它的文件清单比如你升级后配置总是被覆盖就知道rpm对配置文件是有特殊处理的并不是无脑覆盖。1.2 rpmdbRPM的心脏RPM把系统上所有安装过的包信息记录在一个本地数据库里即/var/lib/rpm目录下的那些文件老版本叫rpmdb。你用rpm -qa能列出所有包本质上就是在查这个数据库而不是扫描磁盘。这个设计带来一个巨大优势RPM可以在卸载时清理干净所有文件并且能快速校验文件完整性。代价是如果你不小心删了或者损坏了/var/lib/rpm整个RPM体系就乱了。我见过有人直接rm -rf /var/lib/rpm想清理空间结果系统连rpm -qa都跑不了最后只能从同版本系统里复制一份rpmdb回去救急。所以这个目录轻易别碰。1.3 RPM与yum/dnf的分工如果RPM是“安装工具箱”那yum/dnf就是“管家”。yum/dnf本身不会直接安装软件它们干的事是读取远程仓库repo里的包索引分析依赖关系然后把需要的RPM包下载到本地缓存再调用RPM完成安装。所以在生产环境里正确的做事顺序是能用yum/dnf的地方绝不用rpm手动装因为yum/dnf会自动解决依赖。只有两种情况你必须手动用rpm一是你手里只有一个单独下载好的rpm文件且你确定它依赖的库系统里已经齐全二是你想做一些查询、校验、提取等诊断动作这些操作yum/dnf做不了。1.4 RPM和apt的区别别被习惯坑了用过Debian/Ubuntu的人可能会把RPM的使用习惯直接迁移过来这里有个关键差异Debian系的dpkg/apt包名格式和依赖处理逻辑和RPM体系有些不同。RPM的包名规范通常是软件名-版本号-发布号.架构.rpm比如vsftpd-3.0.5-oe2203sp1.x86_64.rpm中间用短横线连接架构标识放在扩展名前面。特别要注意的是noarch这个架构标识它表示“不依赖具体CPU架构”通常是纯脚本或文档比如Python写的工具。而x86_64、aarch64、i686这些则直接对应硬件架构。装包之前最好先看一眼架构把x86_64的包装到aarch64机器上rpm会直接拒绝。这一点和apt的体验类似但报错信息更明确一些。2. RPM命令日常使用手册从安装到验证一条龙2.1 安装与升级你真的会用-ihv吗安装RPM包最基础的命令是rpm -ivh package.rpm参数拆开看-i表示install安装、-v表示verbose显示详细信息、-h表示输出hash进度条。如果你要升级一个已经安装的包用-Uvh也就是把-i换成-Urpm -Uvh package.rpm-U和-i的区别在于升级会先卸载旧版本再装新版本并且在卸载前执行旧包的%preun脚本安装新包后执行%post脚本。还有一个容易被人忽略的参数是-Ffreshen它只对“系统里已经存在同名的旧包”时才会升级如果系统里没装过就直接跳过。想批量同步一批包的时候-Fvh非常好用。有一个坑我必须提醒不要用rpm -ivh去覆盖安装一个版本号相同的包除非你明确知道自己在干什么否则可能会造成文件冲突。如果旧包的部分文件被修改过rpm会拒绝安装或者提示冲突这时你通常需要先卸载旧的再装新的。在生产环境升级软件我个人习惯先做一次“演习”也就是加上--test参数rpm -Uvh --test package.rpm这个参数不会真正改动系统只会做依赖检查提前发现缺库、冲突之类的问题非常值得养成习惯。2.2 查询遇到问题先查再动手rpm的查询功能是我日常用得最多的能力关键就是-q配合各种选项。查某个包是否安装、版本号是什么rpm -q nginx列出系统里所有已安装的包rpm -qa查某个文件属于哪个包解决“这个文件哪来的”经典问题rpm -qf /etc/nginx/nginx.conf查一个未安装的rpm包里面包含哪些文件rpm -qlp mysql.rpm查一个已安装包安装了哪些文件rpm -ql nginx查一个包依赖哪些库和程序rpm -qpR mysql.rpm这些查询动作不会动系统多做无妨。比如你拿到一个第三方rpm包先-qlp看一眼文件清单和安装路径再-qpR看依赖心里有底了再动手装能避免大部分装到一半中断的尴尬。2.3 卸载依赖关系会反过来咬你一口卸载一个包的命令是rpm -e 包名注意这里填的是包名不是文件名。比如装的时候是rpm -ivh nginx-1.20.1-10.el9.x86_64.rpm卸载时就要用rpm -e nginx。卸载最大的痛点是依赖关系。如果有一个包B依赖包A你直接卸载Arpm会报错并列出哪些包还依赖它。这时你有两个选择一是把依赖它的包也一起卸载二是用--nodeps强制卸载。关于--nodeps我强烈建议你在生产环境里慎用。强制卸载一个被依赖的包可能导致依赖它的软件变成“残缺状态”表面上还在跑起来全是问题。我曾经在测试环境为了图省事强制卸载了一个glibc相关的包别笑年轻时真干过结果系统里几乎一半命令都废了最后只能重装系统。如果一定要绕过依赖请先评估波及范围并做好快照。2.4 校验与验证怎么知道文件被改动过安全排查和故障定位时rpm -V是我很喜欢的命令rpm -V nginx它的作用是校验系统里的文件属性和内容是否和rpmdb记录的一致。输出里有8个字符位分别代表文件大小、权限、属主、校验和等维度的差异后面跟文件名。比如S.5....T. /etc/nginx/nginx.confS表示文件大小变了5表示MD5校验和变了T表示修改时间变了。这个命令对排查入侵、误改配置、磁盘故障都非常有用。想校验系统里所有已经安装的包可以rpm -Va但注意这个命令会扫描大量文件耗时较长而且像/etc下很多配置文件本来就是被修改过的会输出大量结果需要自己判断哪些是异常。2.5 导入密钥不导密钥装包会报错RPM包在构建时可以签名系统安装时通常会导入发行方官方的GPG公钥用来验证包的真实性和完整性。如果你手动装一个有签名的包但系统里没有对应公钥就会看到NOKEY的警告。处理方式不是简单加--nosignature跳过而是应该先导入对应的公钥。CentOS/RHEL上常见的做法rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-*如果是第三方仓库的包要从官方文档拿到对应公钥并导入。验证签名是安全底线尤其当你从非官方渠道下载了一个rpm包时这一步能避免很多恶意或损坏的包混进系统。3. 实战场景拆解从装MySQL到做一个自己的rpm包3.1 用RPM装MySQL时的依赖问题和组包问题很多人在CentOS上用rpm安装MySQL时都遇到过依赖报错因为MySQL的rpm包分了几个子包mysql-community-server、mysql-community-client、mysql-community-libs、mysql-community-common。它们之间互相有依赖如果只下载了server包然后rpm -ivh硬装肯定会提示缺少某某依赖。最省心的方式是把所有子包下到同一个目录然后一条命令全部装上rpm -ivh mysql-community-*.rpmrpm会先把这一批包放进一个事务里解析出它们之间的内部依赖再统一安装。这个方法也适用于装docker、nginx等被拆成多个子包的软件。但有个前提如果MySQL还依赖系统里没有的第三方库比如libaio、libnuma你仍然得先通过yum装好这些基础依赖。所以我的实操建议是先用rpm -qpR mysql-community-server-*.rpm把依赖列出来逐个确认哪些系统里有、哪些没有缺的用yum先补齐再执行批量安装。3.2 CentOS 7配置阿里云rpm源装包基本靠仓库如果你用的系统是CentOS 7或者类似的RHEL系老版本默认的官方源可能已经停止维护或者慢得让人崩溃最简单的加速方案就是换用国内镜像源。以阿里云为例操作不复杂curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo yum clean all yum makecache换源的核心思路是yum/dnf本身只是一个壳真正下载rpm包的地址都写在.repo文件里。把指向官方源的地址改成指向国内镜像剩下的逻辑完全不变。阿里云、腾讯云、华为云都有自己的镜像站选择逻辑都一样。需要注意一点修改.repo文件之后一定要执行yum clean all清掉旧缓存否则可能还会从旧地址拉取索引起不到加速效果。还有CentOS 7已经进入生命周期尾声如果你还在生产环境用它建议尽早规划迁移到Rocky Linux、AlmaLinux等接续发行版这属于运维层面的长期考量越早越好。3.3 制作自己的RPM包别让源码编译的苦再来一次玩到后面你可能会遇到这种需求官方仓库没有某个软件或者版本太老你只能从源码编译。但源码编译出来的东西直接散在系统里后续卸载、升级、版本管理都很麻烦。这时候就应该自己打一个rpm包。打包工具是rpmbuild核心是写一个.spec文件。以MySQL 8.0.36源码包为例大致流程是安装打包工具和依赖yum install rpm-build gcc gcc-c make cmake创建工作目录rpmdev-setuptree会在家目录下生成rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}这几个目录。把源码包放到SOURCES目录在SPECS目录写spec文件。运行rpmbuild -ba 包名.spec构建完成后在RPMS/x86_64下生成二进制rpm包。一个最简spec文件长这样Name: hello Version: 1.0 Release: 1 Summary: A simple hello world package License: MIT %description A simple test package. %prep %setup -q %build make %install make install DESTDIR%{buildroot} %files /usr/bin/hellospec文件里最难理解的是%install段里的DESTDIR%{buildroot}这是rpm打包和普通make install最大的区别你不能直接把文件装进系统而是装到一个临时目录buildroot里等打包完成后再由rpm安装到真实系统。不理解这个逻辑会导致打出来的包文件路径乱七八糟。如果只是想快速把一个已编译好的二进制打成rpm包可以不用让rpm去编译直接在%install里用install命令把你的文件复制进buildroot即可。这种方式虽然“不正规”但很多内部工具分发都在用。3.4 跨发行版的RPM包Fedora上装QQ这类国产软件热搜词里有“Fedora安装QQ rpm”这个场景很有代表性。像腾讯QQ、WPS这类国产软件官方提供的基本是.deb和.rpm两种格式但rpm包往往针对OpenSUSE或Fedora构建不一定完全兼容所有RHEL系发行版。在Fedora上安装这类第三方rpm包常见问题和解决方案缺依赖库报错信息会直接列出缺哪些.so文件或包名优先尝试用dnf install补齐。动态链接库版本不匹配比如软件依赖libssl.so.1.1但你的系统只有libssl.so.3这种单纯靠rpm是解决不了的需要评估软件是否有新版本或者是否愿意自己编译适配。与Wayland/X11的兼容问题某些GUI软件在Fedora默认的Wayland环境下表现异常可以尝试切换到Xorg会话运行。我的经验是装这类包时不要一上来就rpm -ivh先rpm -qpR看依赖再检查系统和软件要求的差距。如果依赖差距过大不如直接放弃rpm改用软件官方提供的其他安装方式比如压缩包解压运行。硬装只会浪费时间。3.5 openssh这类高危软件的rpm升级胆子要大心要细网上很多人在找“openssh rpm包下载”因为OpenSSH是公网服务器最容易被扫描攻击的服务CentOS 7自带的OpenSSH版本已经很老7.4存在大量已知漏洞。于是很多人会去第三方站点下载新版本openssh的rpm包来升级。但这里我必须给你泼一盆冷水OpenSSH不是普通软件升级它之前千万要想清楚后果因为ssh服务一旦配置不当或安装失败你可能会把自己锁在服务器外面。我的建议是先确保你还有别的方式能进系统比如本地控制台、带外管理IPMI/iLO、云厂商的VNC控制台。先把系统的openssh-server、openssh-clients、openssh这几个rpm包备份出来或者找到对应版本的旧包以备回滚。用--test参数先做依赖检查确认新包和系统里其他依赖openssh的包比如openssh-server依赖openssh不会冲突。升级时不要重启sshd服务先测试新二进制能正常执行再手动重启并保持一个已建立的会话不要断开万一坏了还有机会补救。另外第三方站点下载的openssh rpm包来源安全性存疑。除非你确认这个站点可信否则建议优先从发行商官方提供的安全源或经官方维护的第三方仓库获取。安全升级最怕的就是为了堵一个漏洞引入了另一个安全风险。3.6 docker rpm包安装企业内网离线安装利器热搜词里还有“docker rpm包”这也是运维日常高频场景。很多内网服务器是无法访问外网的这时yum install docker根本跑不通你有两个选择一是配置内网镜像源二是提前在外网机器上下载好所有rpm包复制进内网安装。如果走“离线rpm包”路线建议用yumdownloader工具来拉取没有就先yum install yum-utils它可以自动把依赖的包一起下载比手动一个个找包透明得多yumdownloader --resolve --destdir/root/docker-rpms docker-ce docker-ce-cli containerd.io然后把/root/docker-rpms目录打包传到内网机器上执行rpm -ivh /root/docker-rpms/*.rpm这样一套操作下来即使完全离线的环境也能把docker装好。注意下载时要选择和目标机器操作系统版本完全一致的仓库否则依赖库的版本会对不上这个坑我踩过不止一次。4. 常见问题与排查技巧实录4.1 “没找到rpm命令”是怎么回事热搜词里第一个就是“没找到rpm命令”这个问题看着低级实际很容易碰到。最小化安装的CentOS容器镜像、某些精简版系统、或者刚从一个非RHEL系系统切过来的人都可能遭遇bash: rpm: command not found。排查思路是先确认你这到底是不是RHEL系系统。如果是Debian/Ubuntu那就压根不该用rpm如果用cat /etc/os-release确认是CentOS/RHEL系却没rpm命令大概率是精简环境。CentOS/RHEL最小化安装一般都会带rpm但容器基础镜像不一定。解决办法是在Dockerfile里加一句RUN yum install -y rpm如果你连yum都没有那就先装yum或dnf。再极端一点如果所有包管理器都没有可以考虑直接用curl从阿里云镜像站下载rpm包再用cpio解开使用但这种情况已经属于手工作业只适合临时救急。4.2 依赖地狱缺库、缺包、缺依赖这是rpm使用过程中最普遍的问题。常见的报错格式是error: Failed dependencies: libxxx.so.1()(64bit) is needed by package注意它报的是.so文件而不是包名。遇到这种报错你的目标不是找到这个.so文件然后复制进系统而是找到“提供这个.so文件的包”。用yum whatprovides命令可以搜yum whatprovides */libxxx.so.1它会列出提供该库的包然后装那个包即可。这个思路比网上一顿搜索要高效得多。如果你真要面对的依赖是一大串建议先检查是否有多版本共存的问题。比如系统里已经有一个老版本的libssl新版本的rpm包要求另一个版本两个版本的库其实是可以在系统里共存的文件名不同只要rpm找到对应的包名和版本就行。这时候rpm -qa | grep ssl看一下现状再决定是升级还是装兼容库。4.3 文件冲突和已有的文件“撞车”了安装时还有一类常见报错file /usr/bin/foo from install of bar-1.0 conflicts with file from package baz-1.2意思是新包要装的文件已经被另一个包占了。这种情况千万不要用--replacefiles强行覆盖因为很可能两个包都是正常包文件的归属权只应该属于其中一个。正确做法是查明两个包里为什么会有同一个文件。常见原因是两个软件都自带了同一个第三方库的旧版本或者系统里已经有老版本的软件而你想装新版本但没加-U而是加-i。后者的处理方法是改成rpm -Uvh升级让rpm先卸掉旧的再装新的。如果真的是两个独立包都想占用同一个配置文件那你需要判断哪一个才是系统里真正需要的保留它另一个包用--nodeps之前先评估是否必要。实在不行可以手动先把冲突文件改名再安装但我个人不推荐这种方式因为它会把系统的状态弄得很“脏”后续排查问题时非常难跟踪。4.4 密钥、签名与校验安全底线别放松安装从第三方下载的rpm包时常见三种报错需要区分清楚NOKEY没有导入这个包对应的GPG公钥。这不代表包一定有问题但你需要主动去确认包的来源。BAD SIGNATURE签名校验失败。这个比较严重说明包可能被篡改过或者公钥不对通常不建议继续装。DIGESTS SIGNATURES之类的校验错误原因和上一条类似谨慎处理。对于生产环境我强烈建议把“验证签名”当成习惯。即使是内部自己打的包也最好配置好签名流程。系统安全往往败在日常的“图省事”上。4.5 rpmdb损坏让人头痛的一个场景前面提到/var/lib/rpm是rpm的数据库它的损坏通常是意外断电、磁盘满、强制kill进程导致的。症状是执行任何rpm命令都报错比如rpmdb: Lock table is out of available locker entries error: cannot open Packages database in /var/lib/rpm处理思路先说反面教材不要直接删掉rpmdb目录重建那样系统里上千个包的记录就全没了后续卸载升级都会抓瞎。正确思路是备份并重建mv /var/lib/rpm /var/lib/rpm.bak mkdir /var/lib/rpm但这样重建后rpmdb是空的你需要用rpm -qa都没结果了此时最好有系统安装时的原始rpmdb备份。最稳妥的方法还是从同版本机器上复制一份/var/lib/rpm目录——但前提是两边的包列表基本一致否则查询到的包和实际安装的文件对不上一样坑。平时做备份时别忘了把/var/lib/rpm纳入备份范围。这个目录看着不起眼关键时刻能救命。5. 一些关于RPM的“为什么”和“怎么办”5.1 为什么安装一个包会执行脚本很多新手看到rpm装包时输出一堆Running %post之类的内容会觉得莫名其妙。这部分其实是包制作者在spec文件里定义的安装后动作比如创建系统用户、设置权限、注册systemd服务等。这就解释了为什么不要用解压tar包的方式替代rpm安装tar包只能把文件放到位但无法执行这些配置脚本。表面上“好像装好了”实际服务起不来、用户没建好、权限不对各种隐性问题。所以宁可用rpm老老实实装也别自作聪明去“解密”。5.2 包名、文件名、命令名三者别搞混装包时写文件名卸载时写包名查询时可能用命令名。比如文件叫nginx-1.20.1-10.el9.x86_64.rpm包名叫nginx命令名是nginx在/usr/sbin/nginx。rpm -q nginx查的是包rpm -qf /usr/sbin/nginx查的是文件归属nginx -v读取的是命令版本。三者看似一回事实际在rpm语境里是不同维度的对象。搞混了就可能在排查问题时走弯路。比如你遇到nginx命令不见了用rpm -qf /usr/sbin/nginx会提示文件不存在这时候要查的是rpm -qa | grep nginx看看包本身是否正常。如果包在命令却没了那可能是文件被误删用rpm -V nginx校验一下然后在确认系统状态的情况下重装一次。5.3 如何判断一个第三方rpm包是否可以信任第三方提供的rpm包来源复杂程度差异很大。我判断是否可用通常看四件事渠道是否官方优先从软件官网、发行方官方仓库、知名镜像站获取。签名是否有有签名的包至少说明发布者在意完整性导入了对应的公钥后可以验证。文件清单是否合理用rpm -qlp看看文件都装到哪里去有没有可疑路径比如/tmp下的可执行文件。依赖是否合理一个正常软件的依赖通常可预期如果依赖了一堆名字可疑的包就要警惕。安全上没有侥幸可言。许多服务器被入侵都是因为装了来路不明的软件包。多花两分钟做验证比出事之后花几个小时排查要划算得多。5.4 从源码打到rpm包这条路值得走很多开发会觉得“打包”是运维的事实际上掌握rpm打包对开发也有价值。项目交付给客户、部署到多台机器、应对离线环境一个干净的rpm包能让交付体验大幅提升。入门可以先用rpmdev-setuptree建目录再从一个最简单的spec文件开始里面只做文件复制不涉及编译。跑通之后再尝试加上%pre/%post脚本处理服务注册、配置文件生成等逻辑。等你把一个真实的项目成功打包并放到一台全新机器上干净安装时你会觉得之前那些源码编译的痛苦都值了。6. 最后再分享一点我的个人习惯RPM本身并不复杂翻来覆去就那些命令。真正让人翻车的是在没搞清状态的情况下乱操作。我现在无论装什么包都会先在一个临时环境里把命令跑一遍尤其是rpm -Uvh --test这种只检查不生效的选项性价比极高。还有一点处理rpm相关问题时尽量让系统的包管理状态保持“干净”。能不手动改系统库文件就不改能不用--nodeps就不用能用仓库源解决就不到处找rpm文件。系统的包管理数据库一旦被折腾得乱七八糟排查问题的时间成本会成倍上涨。如果你读完这篇文章后能对眼前那个.rpm文件多一份判断力——知道它里面是什么、依赖什么、装到哪、怎么卸载、怎么验证那说明你已经从一个“敲命令的人”变成了一个“知道为什么敲这条命令的人”。这个区别在运维路上非常重要。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门