尧图精选

apt-get 包管理原理与实战:安装、卸载、更新、查询全解析

🕒 发布时间:2026/10/2 3:32:16 📁 来源:尧图网络
1. 先把 apt-get 这套机制想明白再动手敲命令sudo apt-get install这条命令大概是每个碰过 Debian 系系统的人敲得最多的东西。安装软件包、卸载软件包、更新软件包索引、查询软件包信息日常运维里翻来覆去就是这四件事。可我见过太多人用了两三年遇到无法定位软件包或者软件包似乎无效还是一脸茫然最后靠重装系统解决。问题的根子不在命令记不熟而在于不知道这几条命令背后到底动了哪些文件、改了哪些状态。这篇东西我想把 apt-get 这一套从原理到实操捋一遍重点讲安装、卸载、更新、查询四条主线顺带把apt-get download、离线安装、无法定位软件包的定位思路、半安装状态的修复这些真实场景里的坑都带上。适合刚接触 Linux 的朋友打底子也适合已经能跑命令但说不清为什么的人补一下底层逻辑。我个人的看法是apt-get 本身没那么复杂复杂的是它背后那一套「源列表 索引缓存 依赖树 包状态库」的组合。你把这四个东西的关系理清绝大多数报错都能自己推出来是哪一环断了。1.1 apt、apt-get、dpkg、apt-cache 各管哪一摊很多人把 apt、apt-get、apt-cache、dpkg 混着用其实分工很明确理清这一点能省掉很多绕路。dpkg是最底层的包管理工具它只负责把.deb文件解开、铺到文件系统上、把安装状态写进/var/lib/dpkg/status。它不管依赖你给它一个包它就装缺依赖它也只是报错不会自动去帮你找。所以直接dpkg -i装包经常出现「依赖关系没满足」的提示。apt-get是 dpkg 之上的一层封装它做三件 dpkg 不做的事自动解析和下载依赖、从软件源拉取包、维护依赖关系数据库。apt-get install时你会看到「下列【新】软件包将被安装」那一段就是它在算依赖树。apt-cache专门负责查询不产生任何安装动作是只看不动的工具。查包、查版本、查依赖、查反向依赖都归它。apt是后来推出来的统一命令把 apt-get 和 apt-cache 的常用功能揉在一起输出更友好还带进度条。但注意apt的 CLI 输出格式不保证向后兼容写脚本时官方建议还是用apt-get。所以你在文档里看到apt install和apt-get install功能基本一样脚本里优先前者以外的那个。一个容易被忽略的点apt-get的所有元数据都存在/var/lib/apt/lists/里这是从软件源下载下来的「包索引」。apt-get update干的事就是刷新这个目录。而每个包在本地装了没有、装到哪个版本记录在/var/lib/dpkg/status。这俩文件是两套东西别混。很多「明明 update 过了还提示找不到包」的问题就是源索引里压根没有这个包而不是本地状态有问题。1.2 软件包从哪来源列表、索引缓存与依赖树的三角关系把软件源想象成一个巨大的线上仓库/etc/apt/sources.list和/etc/apt/sources.list.d/里的文件就是仓库地址清单。每次apt-get updateapt 会挨个访问这些地址把每个仓库的「货物清单」也就是 Packages 索引文件下载到/var/lib/apt/lists/。这个过程只下载清单不下载任何实际的软件包本体。这一步很多人误解以为 update 就是把软件更新了其实它只是刷新了「货架目录」。真正的包体在你执行 install 时才会去下载下载的.deb会临时放在/var/cache/apt/archives/。第三个角色是依赖树。每个包在自己的元数据里写明了「我需要哪些包」「我和谁冲突」「我替换了谁」。apt 拿到你要装的包名后会在索引里做一次依赖求解算出需要一并安装的包集合。如果这个集合里有任何一环在索引里找不到就会直接失败报出那个经典的E: 无法定位软件包 xxx。理解了这三者的关系你就有了排查的固定套路报「无法定位」先怀疑索引里没有源问题或没 update报「依赖关系不满足」怀疑依赖树求解失败通常是源里缺少某个依赖或者本地已有包把依赖卡住了报「软件包似乎无效」多半是包本身有问题下载不完整、架构不对、不是 Debian 格式。Ubuntu 从 24.04 起开始推 deb822 格式的源文件放在/etc/apt/sources.list.d/ubuntu.sources长得像 YAML 的多段结构和老的单行deb http://... jammy main写法不一样。两种格式 apt 都认但改源之前先看清楚你的系统用的是哪种改错位置等于白改。2. 安装软件包从一条 apt-get install 到离线 deb 的完整路径安装是 apt-get 最核心的功能也是花样最多的一块。从最普通的联网安装到没有外网时的离线搬运再到指定版本回退每一种场景的坑都不一样。这一章我把安装这条线拆成三段讲标准流程、找不到包的排查、离线与指定版本的做法。2.1 标准安装流程与几个真正有用的参数最基础的用法不用多说sudo apt-get install 包名。但有几个参数是真的能救命我按使用频率排一下。-y是自动确认装一堆包时不用一直敲回车。写自动化脚本必加手动装单个包时我反而建议不加因为你需要看清它准备装哪些东西、准备删哪些东西。--no-install-recommends值得单独说。Debian 系把一个包的依赖分成两类Depends必须和 Recommends推荐。默认 apt 会把 Recommends 也装上。这在桌面环境里体验很好但在服务器上就是灾难——你只想装个curl结果它顺手拉进来几十个你根本用不到的库。加这个参数只装硬依赖镜像体积能小一大截。实测下来一个精简的服务器环境加上它初次装常用工具的磁盘占用能少三到四成。-f是修复依赖全称--fix-broken。当你因为各种原因让系统进入「依赖不完整」的状态时sudo apt-get install -f会让 apt 尝试把缺的补上、把多余的清掉。这个命令我把它当急救药用后面讲卸载时还会提到。--dry-run简写-s是空跑一遍只打印它「打算做什么」不真正执行。升级生产环境前我一定会先-s跑一次把输出从头看到尾确认它不会顺手删掉我依赖的组件。--reinstall用于重装当前已装的包覆盖被误改的文件配置文件一般不动。还有一个很实用的apt-get install ./本地包.deb。从 apt 1.1 开始直接在 install 后面跟一个本地.deb的相对路径apt 会识别它是本地文件并且自动帮你解析和下载它缺的依赖。这比dpkg -i好太多dpkg -i缺依赖只能报错还得你自己一条条补。一个真实的安装记录长这样sudo apt-get update sudo apt-get install -y --no-install-recommends openssh-server输出会先列「将要安装的软件包」集合然后是下载体积、磁盘占用估算最后才是实际下载和解包配置。注意到「将要安装」那段的位置特别关键它是在下载之前打印的这就是给你最后一次反悔的机会。注意apt-get install后面跟的包名是精确匹配或前缀匹配不是模糊搜索。你知道大概叫ssh但不确定全名应该先用apt-cache search ssh搜而不是硬猜。猜错的结果就是那句让人抓狂的无法定位软件包。2.2 无法定位软件包三步定位法E: 无法定位软件包 ros-noetic-desktop-full这类报错是新手最容易卡住的地方。我把它拆成三步按顺序排除基本都能找到原因。第一步确认名字对不对。包名区分大小写也不接受连字符和空格混用。先搜apt-cache search ros-noetic如果搜出来一堆相关包但没有你要的那个说明名字错了如果一条都没有往第二步走。有个细节apt-cache search默认只搜包名和简介关键词太宽会刷屏可以配合grepapt-cache search ros | grep -i desktop第二步确认该包所在的软件源有没有启用。这一步是绝大多数「无法定位」的真正原因。Debian 系把仓库分了好几个组件main是官方维护的自由软件restricted、universe、multiverse在 Ubuntu 上是额外组件。你装 ROS 这类第三方生态的包很多时候需要往源里加对应的仓库或者启用universe。看一眼当前启用的是哪些grep -rh ^deb /etc/apt/sources.list /etc/apt/sources.list.d/如果universe没出现而你要装的包正好在里面那就是它了。第三步确认 update 是不是本地的索引过期了。索引过期不会让你找不到包但会让你找到的是旧的包名或旧版本。某个包在新版本里改名了你按老名字装就会报找不到。所以排查时先跑一次sudo apt-get update有个非常隐蔽的坑update输出里如果有仓库 ... 没有 Release 文件或者404 Not Found说明某个源的地址或代号写错了比如把jammy写成了focal。这种源会被 apt 静默跳过索引里自然就没有它里面的包。排查时一定要把 update 的完整输出读一遍别只看到没报错就以为成功了。还有一种情况是架构不匹配。你在 x86 机器上想装某个只给 ARM 打包的包索引里本身就不存在这个组合也会报无法定位。用dpkg --print-architecture确认当前架构。2.3 apt-get download 与离线环境的搬运方案内网机器没有外网是运维里特别常见的场景。做法很朴素在一台能上网、系统版本和目标机一致的机器上把.deb下载下来拷过去离线安装。apt-get download专门干这个它只下载不安装mkdir /tmp/offline cd /tmp/offline apt-get download nginx ls -lh下载完你会得到一个.deb文件。但这里有个坑apt-get download只下载指定的那一个包不下载它的依赖。所以拷过去dpkg -i时极可能缺依赖。两种应对思路思路一把依赖也一起下。先看清楚要装什么再逐个下载apt-cache depends nginx看输出的 Depends 那一行把依赖一个个apt-get download下来最后一起拷过去。思路二直接在一台同样系统的干净机器上用apt-get install --download-only下载完整依赖链。这个参数会走完 install 的全部流程把该下的包全都下到/var/cache/apt/archives/但不执行安装sudo apt-get install --download-only -y --no-install-recommends nginx然后把这个目录里的.deb全部拷到目标机在目标机里进入该目录执行sudo apt-get install ./*.deb对你没看错apt-get install后面可以直接跟通配符展开的一堆本地 debapt 会一起处理依赖顺序。这个方法我在内网部署里用了很多次比逐个dpkg -i稳得多。记得把目标机的/var/lib/apt/lists/索引也一起拷过去否则 apt 可能因为没有索引而无法判断依赖。如果要下载某个包的指定版本语法是apt-get download 包名版本号版本号从apt-cache policy 包名的输出里取那个表格里会列出所有可用版本和它们的优先级很有参考价值。3. 卸载与清理remove、purge、autoremove 的边界在哪卸载看起来最简单实际是四个操作里最容易留下隐患的。我见过有人为了卸一个输入法执行完autoremove之后桌面环境整个不见了。这一章把卸载的边界讲清楚。3.1 remove 和 purge 到底差在哪一句话总结remove删程序保留配置purge连配置一起删。remove会把包标记为「已移除」把程序文件从磁盘删掉但/etc下的配置文件原地保留。你如果之后重新装这个包之前的配置还在会直接生效。这在升级、重装时很有价值。purge是彻底清除程序文件和配置文件一起删。当你确定不再用某个软件、想留一份干净的机器时用它。sudo apt-get remove nginx sudo apt-get purge nginx有个特别容易忽视的点很多服务在运行期间会在/var/log、/var/lib、/home/用户下生成自己的数据文件这些不属于包管理范围无论 remove 还是 purge 都不会删。你要是真想清干净卸完还得手动去这几个目录里找残留。常见的比如数据库的数据目录、应用生成的缓存目录卸载后依然占着空间。卸载前我习惯先看一眼这个包到底带了哪些文件避免删错或者删不干净dpkg -L 包名 | head -50dpkg -L列出这个包安装的所有文件路径输出太长就配head或者grep /etc只看配置部分。3.2 autoremove 的风险控制与残留依赖apt-get autoremove的作用是把「当初作为依赖被自动装进来、但现在没有任何包再需要它」的包清掉。听起来人畜无害实际操作中坑挺深。它靠一个「自动安装标记」来判断。安装某个包时作为它依赖被顺带装进来的包会被打上 auto 标记你手动apt-get install xxx装的包则没有这个标记。autoremove只删带 auto 标记且不再被依赖的。问题在于标记有时候会「失真」。比如某个包最初是被依赖引入的后来你手动用它用得多了或者某个桌面组件的依赖关系被人为改动过。这时候autoremove给出的清单可能包含你不希望删的东西。所以我的习惯是执行 autoremove 前一定先空跑一次sudo apt-get autoremove --dry-run把要删的清单从头到尾扫一遍。看到一个你还在用、但没印象是什么时候装的包先记下来去查apt-cache rdepends 包名rdepends是反向依赖列出「谁依赖我」。如果这个列表是空的说明它确实没人要了删掉问题不大如果列表里有你正在用的东西那 autoremove 就是在误判得用apt-mark manual 包名给它打上手动标记把它保护起来。还有一招是给某个包上锁禁止它被升级或删除sudo apt-mark hold 包名 sudo apt-mark unhold 包名 sudo apt-mark showhold服务器上跑着内核、数据库这类关键组件时把相关包 hold 住是很省心的做法。升级时 apt 会明确告诉你「下列软件包已被保留」不会动它们。3.3 半安装状态与 dpkg 卡死急救三连卸载或安装中途被强制中断断电、CtrlC、磁盘满包会进入一种「半安装」状态文件铺了一半状态库里的标记是iF或者iU而不是正常的ii。这时候任何 apt 操作都会被卡住报一堆「需要重新安装」或者「依赖未满足」。急救第一步看当前状态dpkg -l | grep -v ^ii | head -20正常情况下几乎所有包都是ii期望安装、已安装。出现iF半配置、iU解包未配置就是有问题了。急救第二步让 dpkg 把没配完的继续配完sudo dpkg --configure -a急救第三步如果 configure 之后还有依赖问题用-f收拾sudo apt-get install -f这三步走下来九成以上的 dpkg 卡死都能恢复。剩下的那部分通常是磁盘满了或者/var/lib/dpkg/status真的损坏了。磁盘满就清一下/var/cache/apt/archives/里的旧包sudo apt-get clean sudo du -sh /var/cache/apt/archives/clean是清空整个下载缓存autoclean是只清过期的旧版本包。定时任务里我一般用autoclean保留最近的一份重装时还能直接复用。注意还有一种非常常见的错误是E: 无法获得锁 /var/lib/dpkg/lock-frontend说「有另一个进程正在使用它」。这说明后台有 apt 或 dpkg 在跑最常见的是系统自动更新任务。别急着 rm 锁文件先看看是谁在用ps aux | grep -E apt|dpkg | grep -v grep确认没有活跃进程等它跑完再操作实在卡死了再考虑处理锁文件。暴力删锁带来的后果可能比等待严重得多。4. 更新与升级update、upgrade、dist-upgrade 的分工更新这块是四个操作里概念最容易混淆的。新手经常把apt-get update和apt-get upgrade当成一件事还有人直接用dist-upgrade当作万能升级。这几条命令的边界必须掰开讲。4.1 update 和 upgrade 为什么必须分开apt-get update只刷新索引不安装任何东西apt-get upgrade按当前索引升级已装包不刷新索引。两者职责分离是 apt 设计上的一个刻意选择。为什么分开因为刷新索引有风险。你在某个时间点更新了索引然后基于它升级升级过程是可预期的但如果 update 和 upgrade 混在一起自动执行你永远不知道自己升到的是几天前还是刚才的新版本。生产环境里我们会把 update 和 upgrade 分成两个明确的步骤中间可能还要人工审核升级清单。标准做法是sudo apt-get update sudo apt-get -s upgrade # 先空跑看一眼 sudo apt-get upgradeapt-get upgrade的特点是保守它不删除任何已装的包也不安装新的包来解决依赖变化。如果某个包升级后需要一个新的依赖而这个依赖当前没装apt 会放弃升级这个包把它留在kept back列表里。这个行为很安全但代价是有些包会长期升不上去。apt-get dist-upgrade则激进得多。它允许安装新包、删除旧包来满足升级后的依赖关系。这是它能处理内核升级、库大版本变更这类复杂情况的原因。名字里的dist指的是「发行版级」不是让你跨大版本升级系统这一点很多人理解错了。现代 apt 里有个等价的命令apt full-upgrade语义更清楚用法和 dist-upgrade 一样。命令是否刷新索引是否安装新包是否删除包适用场景apt-get update是否否定期刷新独立执行apt-get upgrade否否否保守升级生产环境apt-get dist-upgrade否是是内核/库大版本变更apt full-upgrade否是是同上apt 新版推荐从这张表能看出来upgrade和dist-upgrade的差别就集中在「能不能装新包、删旧包」这两列。理解这一点你就知道什么时候该用哪个了。4.2 版本锁定与 hold不想被升级打乱的生产环境生产环境最怕的就是「一次无人值守的自动升级把某个组件升挂了」。控制升级范围的手段主要有两个hold 和 pinning。hold简单粗暴直接冻结某个包的版本sudo apt-mark hold nginx sudo apt-mark unhold nginx被 hold 的包在upgrade和dist-upgrade里都会被跳过。适合内核、数据库、关键服务这类「升级收益小、风险大」的包。查看当前被锁的有哪些apt-mark showholdpinning更灵活通过优先级控制某个包从哪个源、哪个版本安装。配置文件放在/etc/apt/preferences.d/Package: nginx Pin: version 1.18.* Pin-Priority: 1001优先级超过 1000 表示强制降级到这个版本900 到 1000 之间表示优先安装这个版本但不降级。这个机制在「必须锁在老版本但又要参与整体升级」的场景里特别有用。老实说pinning 的语法容易写错而且排查起来不直观我一般优先用 hold只有 hold 表达不了的场景才上 pinning。升级前还有一个必做的动作看一眼升级历史。apt 所有操作都记录在/var/log/apt/history.log出问题回查的时候这个文件是唯一的线索。它记着什么时候、哪个用户、执行了什么命令、装删了哪些包。养成升级前先tail一下的习惯能帮你回忆上一次动过什么。4.3 部分升级与内核更新时的注意事项在内核、显卡驱动这类组件上做升级有几个点必须提前知道。内核更新后不会自动生效。升级会装上新内核但当前运行的内核还是旧的需要重启才切换。所以升级完先别急着关终端确认一下uname -r dpkg -l | grep linux-image | head对比当前运行的内核版本和已安装的最新内核版本如果不一样说明需要重启。旧内核不会自动删。多次升级后/boot分区会被旧内核塞满导致下次装新内核时报「空间不足」。定期清理注意别删当前正在用的那个dpkg -l | grep linux-image sudo apt-get autoremove --purgeautoremove --purge会自动把标记为不再需要的旧内核连同配置一起清掉。不过在容器化的环境里这个操作要格外小心容器通常用的是宿主机的内核容器内部不应该有内核包。库的大版本变更用 upgrade 是做不动的。比如某个 C 库从 5 升到 6很多包依赖关系跟着变upgrade会大量kept back。这时候必须用dist-upgrade或者full-upgrade并且在执行前把-s的输出仔细读一遍重点看「将要删除」那一列确认删掉的都是可以删的。提示升级前如果你机器上有正在运行的关键服务先做好配置备份。apt 在升级某些服务时如果检测到你改过配置文件会停下来问你「配置文件要保留还是替换」这个交互式提示在脚本里会因为无输入而卡住。想避免可以在命令前加DEBIAN_FRONTENDnoninteractive但记得提前想好自己的策略。5. 查询与信息检索用 apt-cache 和 dpkg 解决问题查询这块是很多人跳过的一环觉得装得上就行。但真正遇到问题时能不能快速查清楚「这个包装没装」「缺的依赖谁提供」「这个文件属于哪个包」决定的是一小时还是十分钟解决。5.1 查已装、查可装、查版本与依赖先把常用的查询命令按用途分一下。查已装的包dpkg -l # 列出所有包及状态 dpkg -l | grep nginx # 找特定包 apt list --installed # apt 版输出格式不同dpkg -l的输出前面那两三个字母是状态码ii是正常其他都是异常。我最常用的是配grep -v ^ii一把捞出所有异常的包。查一个包的详细信息apt-cache show 包名 # 全部可用版本的完整元数据 apt-cache policy 包名 # 已装版本、可用版本、源优先级apt-cache policy是我最推荐的一个命令一个输出就能看到四个关键信息本地装的是哪个版本、有哪些候选版本、每个版本来自哪个源、源的优先级。装指定版本前必看。查依赖关系apt-cache depends 包名 # 我依赖谁 apt-cache rdepends 包名 # 谁依赖我rdepends在卸载分析里的价值特别高。想删一个不确定用途的包先看反向依赖如果输出里有你正在用的东西说明不能随便删。查可装的包apt-cache search 关键词 apt-cache search --names-only 关键词 # 只在包名里搜结果更准 apt-cache pkgnames | grep 关键词apt-cache search不加限制的话会搜包名和描述结果经常上百条。--names-only只在包名里匹配精确度高一截。5.2 根据文件反查包dpkg -S 与 apt-file「这个文件是哪个包装的」是排查系统问题的经典需求。比如你发现某个二进制文件不知道从哪来的或者某次误改了文件想恢复知道它属于哪个包就能直接重装覆盖。如果文件已经装在系统上用dpkg -Sdpkg -S /usr/bin/ssh dpkg -S $(which python3)-S是--search的简写它查的是本地文件和你已装包的文件清单的对照表。输出会告诉你这个路径属于哪个包。如果报「找不到」说明这个文件不属于任何包管理安装的包可能是手动编译装上去的。反过来的需求是某个包还没装但我想知道它装了哪些文件。dpkg -L只能查已装的没装的用apt-filesudo apt-get install apt-file sudo apt-file update apt-file list 包名 apt-file search 文件名 # 反查这个文件在哪个包里apt-file需要单独安装并且要更新自己的索引索引比 apt 的大不少但换来的是「装之前就能知道包里有什么」的能力排查「某个命令属于哪个包」时非常好使。dpkg -S和apt-file search的区别值得记一下前者查已装索引来自/var/lib/dpkg/info/后者查可装索引来自远程下载的Contents文件。两个查询的对象完全不同遇到「找不到」时先想清楚该用哪个。6. 常见报错排查速查表与实操心得前面讲了原理和流程这一章把高频报错集中列一下再补一些文档里不会写、但踩过才知道的细节。6.1 常见报错与对应处理报错信息大概率原因处理方向E: 无法定位软件包 xxx源未启用、名字错、索引过期先apt-cache search再查源最后apt-get updateE: 软件包似乎无效下载不完整、架构不符、非 deb 格式清除缓存重下dpkg --print-architecture核对架构依赖关系不满足未安装源里缺依赖或本地包卡依赖apt-get install -f修复--no-install-recommends减少牵连无法获得锁 /var/lib/dpkg/lock-frontend有 apt 进程在跑ps aux确认进程等它结束dpkg 被中断必须重新运行上次操作被强杀dpkg --configure -a再apt-get install -f下列软件包被保留upgrade 无法满足新依赖改用dist-upgrade或查清是哪个包卡住磁盘空间不足/boot 或 / 满旧内核堆积apt-get autoclean、autoremove --purge这张表建议存下来。遇到报错先在上面找对应的行比盲搜强。6.2 我踩过的坑和几条实用心得第一条别在索引没更新时下结论。我有一次在内网机器上排查一个装不上的包翻了半天源配置最后发现是那台机器三个月没update过源里的包名早就改了。现在我处理任何「装不上」的问题第一步永远是sudo apt-get update把这条路先堵死。第二条脚本里别用apt用apt-get。apt的输出格式官方明确说不保证兼容你今天写的grep 已经是最新版明天可能就匹配不上了。写自动化脚本时老老实实apt-get加-y输出稳定。第三条看清楚「将要删除」那一列再回车。dist-upgrade和autoremove都会删包apt 在确认前会明确列出来。养成习惯扫一眼有没有你正在依赖的东西。这一点在服务器上比在个人电脑上重要得多。第四条准备一份离线包的应急清单。网络中断、源地址变更、证书过期这些都不影响你手上已经下好的.deb。我习惯把几台关键服务器常用的包用--download-only下好放进一个目录配合版本号和架构标注关键时刻能救命。第五条知道去哪看日志。问题发生时最直接的证据都在日志里/var/log/apt/history.log记录操作历史/var/log/apt/term.log记录终端输出/var/log/dpkg.log记录 dpkg 层面的文件变动。三份日志对照着看能还原绝大部分操作现场。很多人只知道重装系统是因为没意识到证据其实一直都在。第六条源文件的修改要留痕。改/etc/apt/sources.list之前先复制一份备份命名加上日期。半年后你回来排查问题有了这个备份就能立刻知道当时改了什么。我吃过这个亏改过源又没记结果一个诡异的依赖问题查了两天。第七条容器里别把 apt 当万能工具。容器镜像讲究的是体积apt-get install和apt-get clean要在同一条RUN指令里完成否则下载缓存在上一层镜像里删不掉体积下不来。写法上apt-get update apt-get install -y --no-install-recommends 包名 \ rm -rf /var/lib/apt/lists/*把索引也一起删掉能再省出一部分空间。这个组合在构建精简镜像时几乎是标配。真正把一个包管理工具用熟靠的不是背命令而是形成一套固定的排查顺序先 update 看索引再 search 确认名字再 policy 看版本和来源最后才动手装或卸。这个顺序养成了你会发现以前那些「玄学问题」其实每一步都有确定的答案。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →