
两种包管理体系的查询命令理清楚一次就不会再混了不管你是在 Debian/Ubuntu 上折腾日常环境还是在 CentOS/RHEL 这类 RPM 系服务器上排查问题迟早都会撞上同一个困惑想看一下某个软件到底装没装、装在哪儿、版本是多少明明都是 Linux命令却完全对不上。用dpkg的跑习惯了一换到 RPM 系脑子里全是rpm -qa和yum list的混搭反过来也一样。我早期刚接触 Linux 的时候就因为在 CentOS 上敲apt list --installed被系统提示“command not found”当时还以为是环境坏了折腾了半天才反应过来是包管理体系的差异。这篇内容我会把两条线拆开讲透Debian 系dpkg/apt和 RPM 系rpm/yum/dnf里最常用的软件包查询命令包括列出已安装包、查看包的详细信息、按文件名反查包归属以及最实用的模糊查找技巧。目标就一个——下次你不管拿到哪台机器都能在 30 秒内搞清楚“我要找的东西在不在、是什么版本、文件在哪”。我还会顺手把你实际操作中最高频踩的坑比如“没找到 rpm 命令”、WSL 里装 Debian 后 sudoers 报错、升级内核时驱动和包版本对不上这类一并说完这些内容网上零零散散都有但很多帖子里不会说为什么。适合谁看刚接触 Linux 没多久、被两种包管理器搞晕的新手是最核心的一批读者运维和开发如果你平时只盯着自己常用的发行版没系统整理过另一套体系的命令这篇也能当个速查手册用。我自己是长期 Debian 日常使用、RPM 系线上服务器来回切换的状态所以下面的每个命令都是实际敲过、验证过的不是从 man 手册里抄出来的。1. 包管理体系的底层差异为什么两边命令长得完全不一样1.1 dpkg/apt 与 rpm/yum/dnf 的定位区别先说概念层。Debian 系的底层是dpkg它直接操作.deb包上层是aptapt-get/apt-cache 的新整合版负责处理软件源、依赖关系、下载安装这些更复杂的逻辑。RPM 系的底层是rpm直接操作.rpm包上层是yum或dnfRHEL 8 及之后的默认包管理器功能定位和 apt 完全对等。这个分层关系特别重要因为你会发现凡是和“本地已下载的包文件”直接相关的操作要找底层工具dpkg/rpm凡是和“软件源里的包、依赖解析、在线查找”相关的操作要找上层工具apt/yum/dnf。很多人命令记不住本质上是没分清自己面对的场景到底是本地包还是远程源。打个比方dpkg/rpm 像是一个本地档案管理员你给它一个.deb/.rpm文件它能告诉你这个包里有什么、装了没有、文件都放哪了apt/yum/dnf 更像一个采购员它先通过软件源的索引知道哪里有货、要买哪个还要连带买哪些依赖买回来之后把货交给档案管理员去登记入库。所以查询场景下你想要的“列出已安装包”这种动作其实是档案管理员手里的花名册——dpkg 和 rpm 都能干而“模糊查找一个没安装的软件在源里叫什么名字”那是采购员的活儿——得找 apt 或 yum。1.2 一张命令对照表解决“哪个打哪个”的问题我先把高频查询场景的两边命令列成一张对照表你以后查的时候直接对号入座。查询场景Debian 系命令RPM 系命令列出所有已安装包dpkg -lrpm -qa查看已安装包细节dpkg -s 包名rpm -qi 包名列出包安装的文件清单dpkg -L 包名rpm -ql 包名查找某个文件属于哪个包dpkg -S 文件路径rpm -qf 文件路径在软件源里模糊搜索包apt search 关键词yum search 关键词/dnf search 关键词查看软件源里某个包的详细信息apt show 包名yum info 包名/dnf info 包名查看软件源里包的可安装版本apt-cache policy 包名dnf repoquery --info 包名或yum list 包名这张表不是让你死记硬背而是给你一个记忆锚点底层查本地看 dpkg/rpm上层查源看 apt/yum。你只需要记住 dpkg 对 rpm、apt 对 yum/dnf 这个对仗关系所有的查询命令都是同一结构在不同命名里的映射-l是 list-s/-q是 status/query-L/-q加 l 是 list files-S/-q加 f 是 find package。下面两部分我把每个命令的真实输出和典型用法逐个讲一遍尤其是那些容易被忽略的参数。2. Debian 系dpkg 与 apt 的查询命令全家桶2.1 dpkg 本地包查询四件套先说最基础也最常用的dpkg -l。它列出的是系统里 dpkg 数据库中记录的所有包按字母序排列每条记录的开头有两个字符状态位。比如第一列是ii表示这个包已安装且安装正常如果是rc则表示包已经被删除但配置文件还残留在系统里。这个细节特别实用——我见过很多人在排查系统时发现磁盘里某个软件明明已经卸载了却还在“已安装列表”里看到它其实就是没看状态位直接慌着又装了一遍。dpkg -l # 输出示例截取 DesiredUnknown/Install/Remove/Purge/Hold | StatusNot/Inst/Conf-files/Unpacked/half-conf/Half-inst/trig-aWait/Trig-pend |/ Err?(none)/Reinst-required (Status,Err: uppercasebad) ||/ Name Version Architecture Description ---- ii adduser 3.118 all add and remove users and groups ii apt 2.6.1 amd64 commandline package manager rc example-soft 1.0.0 amd64 (no description was provided)单独查某一个包是否安装用dpkg -l | grep 包名是一种偷懒但完全有效的做法尤其适合模糊匹配。正规一点的姿势是dpkg -s 包名输出里会包含 Package、Status、Version、Installed-Size 等字段。注意dpkg -s不像dpkg -l那种列表模式它是直接打印一段结构化信息很适合在脚本里用grep ^Version提取版本号。再看dpkg -L 包名列出指定包安装的全部文件路径。比如你装了 nginx想知道它的配置文件在哪、二进制在哪、文档在哪一条命令全出来。反过来dpkg -S 文件路径注意是大写 S则是给定一个绝对路径反查这个文件属于哪个包。典型场景是你手头有个/usr/bin/ffprobe不知道是装哪个包带进来的直接dpkg -S /usr/bin/ffprobe就会告诉你属于 libavcodec 相关的某个包。这个命令还有一个很要命的用途当某个文件被不知名的进程占用或污染时反查原包可以快速定位恢复源。2.2 apt 的软件源查询与模糊搜索dpkg只能查已经装好或者包文件已下载到本地的内容要从软件源里搜索一个还没装的软件必须用 apt 家族。apt search 关键词是模糊查找的标配。它的搜索范围是软件源的包名和描述信息所以即使你只记得软件名字里的一两个单词也能搜出来。比如你搜apt search pdf会出现各种和 PDF 相关的工具输出里每个包的描述都很友好适合人眼筛。你如果只想搜包名不搜描述可以加--names-only参数这样结果更精确不会把一堆功能类似但名字无关的包混进来。apt show 包名是查看软件源里某个包的详细信息包括版本、依赖、下载大小、安装大小、维护者等。注意apt show显示的版本未必和你本地装的版本一致——它显示的是从源里能拿到的版本。要看本地已安装包的版本还是建议用上面说的dpkg -s或者apt list --installed | grep 包名。apt-cache policy 包名是一个被低估的命令它能把候选版本信息列得清清楚楚输出里会显示Installed当前已装版本、Candidate系统会选择安装的候选版本、Version table源里所有可用版本以及各自来自哪个源。这个东西在排查“为什么 apt 不给我升到最新版”时是最直接的证据。比如你明明换了源却还是装不到新版本一跑apt-cache policy就能看到候选版本依旧是旧的多半是源优先级或 Release 文件没生效。2.3 实例判断包状态和反查文件的完整流程我拿一个实战场景串一遍 Debian 系的完整查询链路。假设你在 Debian 12 上想确认 nginx 装的是什么版本配置文件在哪个位置同时你又想搞清楚/usr/sbin/nginx这个二进制到底属于哪个包。第一步查是否安装dpkg -l nginx或dpkg -s nginx。如果输出里 Status 是install ok installed说明包在。第二步看版本dpkg -s nginx | grep Version。第三步列文件位置dpkg -L nginx重点看/etc/nginx/下的配置路径。第四步反查二进制归属dpkg -S /usr/sbin/nginx正常情况下它会说这个路径属于 nginx-core 或 nginx 包因为你装的 nginx 可能是元包真实二进制在 nginx-core 里。这个“元包 vs 实际包”的区别很常见查文件归属时你会经常发现你以为管理的是 nginx 这个包实际上系统里住着的是 nginx-core。搞清楚这一层之后你想卸载才不会漏掉真正的载荷包。3. RPM 系rpm / yum / dnf 的查询命令指南3.1 rpm 四件套-qa / -qi / -ql / -qfRPM 系的底层是rpm它的查询参数比 dpkg 更直白但有个大坑参数大小写和组合顺序容易搞混。最常用的rpm -qa是列出所有已安装包q是 querya是 all。输出默认是一行一个包名连同版本和架构比如nginx-1.20.1-10.el9.x86_64这样一大串需要再配合 grep 过滤。rpm -qi 包名里的i是 information直接查看某个已安装包的详细信息包括 Name、Version、Install Date、Group、License 等。重点提醒这里传的包名要尽量完整至少要带上能唯一定位的名字片段。早期我吃过亏以为像 yum 那样写nginx就能查全结果 rpm 严格到要你写对 exact 名字写个nginx-也照样报错误。实际习惯里我都是先rpm -qa | grep nginx拿到完整包名再rpm -qi 完整包名两步走百无一失。rpm -ql 包名list files列出包安装的文件清单。注意它和 dpkg -L 的结构一样每条路径一行文件多的时候输出非常长建议配合grep只筛关心的目录比如rpm -ql nginx-core | grep etc。rpm -qf 文件路径是反查文件归属这里的f是 file。比如/etc/nginx/nginx.conf被改坏了你想知道它是原属于哪个包的好从原始包恢复直接rpm -qf /etc/nginx/nginx.conf。还有两个体征需要知道rpm -qc 包名只列配置文件configrpm -qd 包名只列文档doc这两个是-ql的细分变种排查配置时比全量 file list 更高效。3.2 yum/dnf 查询与源内模糊搜索yum和dnf在高版本 RHEL/CentOS/Fedora 上的地位相当于 apt。你使用时可能遇到 RHEL 系默认已经没有yum了只有dnf不过dnf兼容了绝大多数 yum 的语法和习惯旧脚本里敲yum list在 dnf 下也能执行做了软链兼容只是实际解析引擎不一样。yum list installed是 RPM 系的“列出已安装包”输出比rpm -qa多一列分别是包名、架构、版本、仓库来源比如Installed Packages分节底下的记录。yum list available列出源里可取的所有包yum list all则已安装和可取的都显示适合全局浏览。如果你想确认某个特定包是否已经安装yum list installed | grep 关键字是最快的方式。模糊搜素用yum search 关键词原理和 apt search 一样搜的是源里的包名和描述。你可以得到一个列表然后再用yum info 包名看详细信息包括版本、大小、源、依赖。这里有个细节yum info和rpm -qi看得内容相近但前者能查未安装的包后者只能查已安装的包。所以我个人的习惯是“先 search 再 info确定名字后再决定装不装”。dnf repoquery是 dnf 的一大杀器它提供大量仓库元数据查询功能比如dnf repoquery --info 包名可以显示候选版本里的详细信息dnf repoquery --requires 包名列出依赖dnf repoquery --whatprovides 文件路径反查哪个包提供了某个文件——这比rpm -qf更强的一点是它可以查询仓库中尚未安装的包对文件的提供关系。CentOS 7 的 yum 用户没有 repoquery 原生支持需要yum install yum-utils才能用yum repoquery这也是一个常见坑。3.3 用查询命令验证 RPM 安装的 MySQL 是否成功网上关于“rpm 安装 mysql”的提问非常多最常见的场景是从官网下载了几个.rpm文件用rpm -ivh依次装完然后不知道该怎么验证。我可以给你一套完整的查询验证脚本。安装完成后第一步rpm -qa | grep mysql你会看到类似mysql-community-server-8.0.36-1.el9.x86_64这样的一串如果同时装了 client、common、libs每一行都应该在结果里出现。第二步rpm -qi mysql-community-server看安装信息重点看 Version 和 Install Date。第三步rpm -ql mysql-community-server | head -50你会看到二进制在/usr/sbin/mysqld配置文件在/etc/my.cnf数据目录默认是/var/lib/mysql。如果服务器上已经有其他 mysql 相关包rpm -qf /usr/sbin/mysqld能帮你确认这个二进制到底属于哪个包防止多版本混装时改错文件。这套查询链路不但能确认安装成功与否还能在后续升级、清理包时帮你精确定位对象。4. 模糊查找与实用组合不知道确切包名时怎么搜4.1 包名模糊搜索apt 与 yum/dnf 的差异模糊搜索听起来简单实际有个“搜不到”的尴尬经常发生。比如 Debian 里你想装一个 Markdown 编辑器脑子里第一个词可能是markdown但apt search markdown出来的其实是被描述里包含 markdown 的包带出来的真正的 Typora 或 Obsidian 这类名字里可能根本没有 markdown 字样。这时候你要么换关键词editor、notes要么直接上apt search --names-only配合你已知的包名前缀搜。RPM 系同理dnf search markdown也会出现同样的问题。我个人总结的模糊搜索技巧是不要用一个词搜到底把中文含义翻译成英文后换 3 个以上候选关键词轮流试每轮看输出的包名前缀来推断官方命名词缀。比如搜 PDF 工具先apt search pdf再看里面哪几个包名前缀是pdf-再针对性搜pdf-这个前缀命中率会高很多。另外在 Debian 系上apt-cache search和apt search等价但有些人习惯用前者写脚本两者都可以。4.2 按文件路径反查包归属反查是模糊搜索的逆向场景。你有一个二进制文件或绝对路径想知道它属于哪个包。Debian 用dpkg -S 路径RPM 系用rpm -qf 路径。这里有个关键坑dpkg -S只能查已安装包提供的文件而/usr/bin底下的文件很多时候是 update-alternatives 的软链指向/etc/alternatives/再链到真实路径。比如你dpkg -S /usr/bin/python3大概率会看到结果说这个路径是一个符号链接真正的答案需要dpkg -S加-f参数或者直接对目标位置/usr/bin/python3.11反查。RPM 系也有相同情况但 rpm 查询时会自动解析符号链接指向的真实文件所以rpm -qf一般不会踩这个坑。Debian 用户请务必记住dpkg -S的-f选项--follow不然会以为是包数据库出错。RPM 系里如果文件不属于任何已安装包你会看到error: file /xxx: No such file or directory或者file /xxx is not owned by any package这时候你需要用dnf repoquery --whatprovides 路径去查询软件源里哪个包会提供这个文件。Debian 系没有直接对等的源反查命令通常做法是去 packages.debian.org 的在线文件搜索页面输入路径查询或者安装apt-file工具先apt-file update更新索引再apt-file search 文件路径即可实现离线反查源内文件归属。apt-file这个工具在 Debian 系里的定位就相当于dnf repoquery --whatprovides。4.3 用 grep 过滤和组合命令实现多条件查询单个命令的输出信息往往太多实际用的时候都是组合拳。Debian 系我们常用dpkg -l | grep nginx过滤出包含 nginx 的所有包RPM 系用rpm -qa | grep nginx。如果想同时过滤多个关键词比如查所有同时包含 mysql 和 server 的包可以直接rpm -qa | grep mysql | grep server或者用 grep 的-E扩展正则如rpm -qa | grep -E mysql.*server|server.*mysql。再高级一点的组合是先模糊搜索出包再批量列出文件。比如你想知道所有python3开头的包分别有哪几个、并简述用途可以dpkg -l | grep ^ii | awk {print $2} | grep ^python3把包名提取出来再逐条apt show。RPM 系对应写法是rpm -qa | grep ^python3 | xargs -I {} rpm -qi {}。这种 pipeline 在服务器巡检时非常实用能快速生成一份“已安装软件清单版本描述”的报告。不过要提醒一句dpkg -l的第一行是表头grep 提取时最好先排除掉行首的|或状态位避免把 Desired/Status 那两行也带进去。5. 常见问题与避坑实录5.1 “没找到 rpm 命令”的各种真相在 Debian/Ubuntu 系统里敲rpm会直接提示rpm: command not found这不算系统坏了是发行版默认不装 RPM 生态的组件。如果你确实有临时操作 RPM 包的需求比如解包看内容可以sudo apt install rpm装一个但装了也不代表系统就变成 RPM 系了它只是允许你操作.rpm文件格式不会把 dpkg 换成 rpm。反过来在 CentOS 上敲dpkg也一样不存在。更隐蔽的一种情况是你在 Alpine Linux用的 apk或 Arch Linux用的 pacman上敲rpm也会遇到同样的错误。遇到 “command not found” 时第一反应不是查“怎么装 rpm”而是确认当前系统属于哪个包管理体系。你可以看/etc/os-release文件里的ID字段比如IDdebian或IDcentos这是判断系统身份最可靠的方式。另外Minimal 版 CentOS/RHEL 可能会预装 rpm但未必预装 yum/dnf。我遇到过 CentOS 7 的最小化安装里只有 rpm没有 yum用户想yum install却报 command not found。这种情况要么是/usr/bin/yum真的没装要么是 python 环境被破坏导致 yum 启动脚本失效。排查时先which yum看路径是否存在再看python --version和/usr/libexec/urlgrabber-ext-down这类依赖是否正常。5.2 sudoers 权限问题换源安装时最容易误判的报错很多刚在 WSL 里装完 Debian 的用户会从网上抄一段换源命令然后在执行sudo apt update时看到类似sudo: a 未出现在 sudoers 文件中的报错。这个 “a” 其实是当前用户名比如用户名是a时就会显示这么一条。报错的意思是当前用户不在 sudo 组里或者 sudoers 文件没有给这个用户授权。这和软件源完全无关纯粹是用户权限配置问题。解决办法是在 WSL 的默认用户下用 Windows 侧命令修改如果你是用 wsl 命令进入的根用户可能默认是 root那就不用 sudo 直接可以跑 apt如果你自建了用户需要在 root 身份下执行usermod -aG sudo 用户名把用户加进 sudo 组。在 WSL2 里有个取巧办法如果当前用户真的没有 sudo 权限可以从 Windows 的 PowerShell 里执行wsl -u root进入 root 登录再去修 sudoers 或 usermod。我在多个环境里验证过在/etc/sudoers里直接用visudo或追加用户名 ALL(ALL:ALL) ALL都能解决但更推荐usermod -aG sudo这种正规做法避免直接改 sudoers 造成语法错误把整个提权通道搞挂。5.3 软件源换源与 GPG 报错的处理思路“Debian 13 (Trixie) 换清华源”这种关键字说明很多人在新版本 Debian 上会重复做换源操作。换源的常规思路是把/etc/apt/sources.list或/etc/apt/sources.list.d/下的文件里的源地址改成镜像站比如清华源。但新版本 Debian 从 Bookworm 开始默认启用了 deb822 格式主源信息可能放在/etc/apt/sources.list.d/debian.sources而不是旧的sources.list编辑前先看清楚文件路径改错文件是几乎所有“换源不生效”的根源。换完源后最常碰到的报错是一长串 GPG 错误比如W: GPG error: http://mirrors.ustc.edu.cn/debian trixie InRelease: The following signatures couldnt be verified。这个报错的本质是 APT 在验证软件源的签名时本地没有该源对应的公钥。处理方式有两种一种是用这个源官方提供的包安装公钥比如debian-archive-keyring另一种是手动下载并apt-key add但注意apt-key在多年以前就被标记 deprecated 了现代 Debian 推荐把公钥放到/etc/apt/keyrings/然后在.sources里用Signed-By字段指定公钥位置。关于镜像站的可用性国内用户确实更常访问清华、中科大这类镜像但我不建议把/etc/apt里的安全更新源全部替换成同一个镜像站最好保留官方 security 源用于安全更新镜像站只负责业务软件的下载加速。安全更新的及时性对服务器而言是底线一线运维同事会特别在意这点。5.4 WSL2 里跑 Debian 的查询命令体验WSL2 下跑 Debian 13 的场景越来越多我自己也会在 Windows 上开一个 Debian WSL 做实验环境。WSL2 里的 Linux 是一个完整的发行版所有 dpkg/apt 查询命令都能正常使用但有两个特殊点。第一WSL2 默认是 root 用户的发行版配置你敲dpkg -l看到的是 root 的完整包列表而 Windows 侧的 GUI 软件不会出现在 Linux 包列表里。第二WSL2 的性能和网络跟宿主机共享查询软件源时如果出现网络超时优先怀疑 Windows 侧代理或防火墙配置。另一个常见需求是输入法切换Debian WSL 里装完搜狗输入法后需要配置环境变量WSL 没有传统桌面登录流程输入法启动依赖fcitx或ibus自启动脚本查询时可以用dpkg -l | grep fcitx确认输入法框架装没装再用ps aux | grep fcitx看进程是否存活这两条命令组合起来基本能定位九成的输入法起不来问题。5.5 升级内核和英伟达驱动时的包查询技巧Debian 升级内核后英伟达驱动不匹配是老生常谈的问题。其实思路很简单升级前先记录当前内核版本和驱动包版本升级后对比差异。查询当前内核版本是uname -r查询已安装的英伟达相关包是dpkg -l | grep nvidia。Debian 源里的驱动包命名规律一般是nvidia-driver、nvidia-kernel-dkms、nvidia-driver-bin这么一串。如果你升级内核后驱动模块加载失败多半是 DKMS 没有为新的内核版本重新编译模块此时先dkms status查看模块状态再dpkg -l | grep nvidia | awk {print $2}拿到包名逐个dpkg-reconfigure 包名或者重装nvidia-kernel-dkms触发重编译。整个过程里几乎每一步都在用查询命令不会查列表根本没法定位是哪个包出了问题。6. 一些我个人的使用习惯和建议最后聊点不一样的。上面我按体系把命令都过了一遍但真正要上手快靠的是养成“先身份识别再工具选择”的条件反射。我自己的习惯是登录任何一台陌生机器后第一件事就是cat /etc/os-release | head -2确认系统身份再决定后面用 dpkg 还是 rpm 体系。这个动作比背任何表都管用。另外我还想说一下包查询和包管理的边界。很多人dpkg -l和apt list --installed混着用其实后者在索引更新时性能会比前者差尤其在大型服务器上会产生额外网络开销。纯本地的查询操作优先dpkg -l/rpm -qa需要仓库信息的才用 apt/yum/dnf。这个原则能帮你少踩很多无谓的性能和超时坑。以后碰到新发行版也别慌。哪怕是最不常见的发行版包管理底层永远逃不开 dpkg/rpm/pacman/apk 这几类你能掌握两套主流体系的查询逻辑剩下的无非是根据发行版手册做 10 分钟映射。学习最快的方式不是背命令而是手边准备一台 Debian 和一台 CentOS/RHEL 虚拟机把每一条查询命令实际敲一遍对着输出读一遍字段含义。敲三次以后你会发现那些所谓的“命令大全”全都不是给你背的而是给你验证思路用的。