ARTICLE DETAIL

资讯详情

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

apt-get 全流程实战:安装卸载更新查询与报错排查

apt-get 全流程实战:安装卸载更新查询与报错排查 装软件这件事在 Debian/Ubuntu 系上看上去就是一行命令的事。但真在生产环境里摸过几年的人都知道apt-get这四个字母背后藏着的东西远比想象中多。同样一句sudo apt-get install openssh-server有人三秒装完收工有人卡在无法定位软件包上折腾一下午还有人装完之后系统再也起不来。软件包的安装、卸载、更新、查询这四件事单独拎出来每件都不难难的是把它们串成一套完整的、可复现的、出问题能兜底的流程。这篇内容我打算把这套流程从头到尾捋一遍。不管你是刚装完第一台 Ubuntu 虚拟机的新手还是天天给几十台机器做批量更新的运维都能从里面找到能直接抄的东西。核心主线有四条怎么把包干净地装上去怎么把它连配置一起卸掉怎么安全地更新而不是把自己更新崩以及怎么在装之前和装之后准确地查清楚系统里到底发生了什么。中间会穿插大量报错场景的真实成因和排查路径都是踩过的坑。1. apt-get 到底管什么从 dpkg 到 APT 的分层设计很多人用了很久 apt-get却说不出它和 dpkg 到底什么关系也不知道为什么会有 apt 和 apt-get 两个命令。搞清楚这一层后面所有报错的成因基本都能自己推出来。1.1 三个层级dpkg、apt、apt-get 各管一段最底下是dpkg。它是 Debian 系真正干活的安装器只认识一个.deb文件能力非常窄把包里的文件解压到对应目录、执行包里的安装脚本、在数据库里登记一行记录。它完全不管依赖。你给它一个 deb它就去装缺什么库它不管装完能不能跑它也不管。中间层是APTAdvanced Package Tool它是一整套体系包含软件源配置、依赖求解器、下载器、缓存管理、状态数据库。apt、apt-get、apt-cache都是这套体系的命令行前端只是分工和年代不同。APT 干的事是读源里的索引 → 算出一组满足依赖的包 → 按顺序下载 → 交给 dpkg 装 → 处理装完之后的状态。最上面才是我们敲命令的那一层。所以你敲apt-get install时实际上发生了五六件事更新索引可能被触发、依赖被求解、包被下载到/var/cache/apt/archives、dpkg 被循环调用、/var/lib/dpkg/status被更新。这也是为什么 apt 装包比直接dpkg -i安全得多——依赖求解这一层是 apt 存在的全部意义。提示/var/lib/dpkg/status是系统里所有已安装包的真实账本。这个文件坏了apt 基本就废了动手前记得备份。1.2 为什么会有 apt 和 apt-get 两个命令apt-get是老前端从 1998 年用到现在特点是输出稳定、脚本友好、行为保守几乎所有自动化脚本和文档都基于它。apt是 2014 年前后才出现的新人友好版它把apt-get和apt-cache的常用功能合到一起加了进度条和更漂亮的输出并且在执行upgrade时会自动提示有多少包要升级、多少要新装、多少要删除。但是apt的输出格式被明确声明为不稳定、不保证向后兼容官方文档里写得很直白脚本里请用apt-get。这就是为什么你会在各种安装文档、Dockerfile、Ansible playbook 里看到的都是apt-get而不是apt。我自己的一套判断标准是这样的手动在终端里敲用apt更舒服写进脚本、写进 CI、写进 Dockerfile一律用apt-get并且加上-y和DEBIAN_FRONTENDnoninteractive。1.3 软件源才是真正的上游命令只是入口一个特别容易被忽略的事实apt-get本身不知道任何软件的存在。它只是去读/etc/apt/sources.list和/etc/apt/sources.list.d/下面配置的源地址把那边提供的索引文件拉下来然后在这份索引里搜索。索引里没有的包你在本地怎么折腾都装不上。这直接解释了两个高频困惑为什么ros-noetic-desktop-full死活装不上因为默认源里根本没有它必须先进 ROS 的源为什么某个包昨天还能装今天就不行了因为源里的索引变了或者某个版本被上游撤了。Ubuntu 24.04 之后源配置格式从传统的单行式换成了新的 deb822 格式文件在/etc/apt/sources.list.d/ubuntu.sources长这样Types: deb URIs: https://mirrors.tuna.tsinghua.edu.cn/ubuntu Suites: noble noble-updates noble-backports Components: main restricted universe multiverse Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg老的sources.list格式依然能用两种格式可以共存。但如果你在 24.04 上往sources.list里加东西却发现没生效八成就是这个问题——新版本优先读 deb822 文件你的修改被覆盖了。2. 核心命令族拆解安装、卸载、更新、查询四条主线命令本身不难记难的是同类命令之间的差异。install 和 reinstall 差在哪、remove 和 purge 差在哪、update 和 upgrade 差在哪——这些差异在实际操作里全是坑。2.1 安装install 和它的三个兄弟最常用的当然是installsudo apt-get install openssh-server但装包这个动作至少有四种变体值得记住命令适用场景关键差异apt-get install pkg常规安装有依赖会一并装已装则跳过apt-get install --reinstall pkg文件被误删/改坏强制重下重装配置默认保留apt-get -f install依赖破损时修复未满足的依赖常配合 dpkg -i 使用apt-get download pkg只要 deb 文件只下载到当前目录不安装--reinstall这个参数我用了很多次。典型场景是某个包的核心文件被误删或者被手工覆盖了比如openssh-server的 systemd unit 文件被改坏直接重装比一个个文件去恢复快得多。注意它默认不覆盖配置文件因为 dpkg 对标记为 conffile 的文件有保护机制会问你要不要保留旧配置。apt-get download则是离线部署的核心。在能上网的机器上把所有依赖下下来拷到内网机器上dpkg -i *.deb这是隔离环境里最常用的手法。但要注意apt-get download只下一个包不解析依赖依赖得你自己用apt-cache depends一个个找出来下或者用apt-get install --download-only让它把整棵依赖树都拉到缓存里。# 把整棵依赖树下载到 /var/cache/apt/archives不安装 sudo apt-get install --download-only -y nginx # 或者指定下载目录 sudo apt-get -o Dir::Cache::archives/tmp/debs install --download-only -y nginx最后那句-o Dir::Cache::archives...是我在离线场景里最常用的技巧比默认缓存目录好找得多。2.2 卸载remove 与 purge 的边界在哪sudo apt-get remove nginx # 删程序保留 /etc 下的配置 sudo apt-get purge nginx # 连配置文件一起删 sudo apt-get autoremove # 清理不再被依赖的孤立包 sudo apt-get autoremove --purge # 连孤立包的配置一起清remove和purge的差别看起来只是要不要留配置文件但实际影响面很大。举个真实的例子你 purge 掉mysql-server/etc/mysql和/var/lib/mysql会被一起清掉数据直接没了remove则只删二进制数据目录还留着。反过来如果你是想彻底重装一个配置被改乱的软件光remove然后install是没用的旧配置还在apt 会直接沿用行为一模一样。判断残留状态有个很好用的命令dpkg -l | grep ^rc输出里状态是rc的就是已删除但配置还在的包。批量清理dpkg -l | awk /^rc/ {print $2} | xargs sudo apt-get purge -y注意autoremove在你手工装过某些看起来没人依赖的库时要格外小心。它只根据依赖关系判断如果某个包是你手动装的但恰好没有别的包依赖它而你自己也忘了它就会被清掉。执行前先看一眼它打算删什么。2.3 更新update、upgrade、upgrade 的三种姿势这一组是出事故最多的地方必须分清楚apt-get update只更新索引。从源拉最新的包列表不动系统里任何一个已安装的包。这个命令本身是安全的可以随时执行。apt-get upgrade升级所有已安装的包但绝不删除已有包也绝不安装新包。如果某个升级需要引入新的依赖那个包会被保留不升级。apt-get dist-upgrade/apt full-upgrade允许为了完成升级而安装新包、删除旧包。内核升级、依赖关系大改的场景必须用它。upgrade 和 dist-upgrade 选哪个这个问题我的经验是日常维护用upgrade遇到有包被 hold 住、或者官方公告说要做内核/驱动更新时用dist-upgrade。dist-upgrade的允许删除这一条是双刃剑它可能为了升级某个库而删掉一批你正在用的包所以执行前一定要看它列出的删除列表。# 先模拟一遍看清楚会发生什么 sudo apt-get -s dist-upgrade # 确认没问题再真跑 sudo apt-get dist-upgrade-s就是--simulate不写盘、不下载只输出计划。这个习惯我建议一直保持尤其是对生产机器。还有一个坑apt-get update如果因为某个源不可达而失败整条命令会返回非零退出码但其他源的索引其实已经更新成功了。这会导致脚本里的set -e直接中断。稳妥的写法是sudo apt-get update || true sudo apt-get install -y --no-install-recommends nginx或者在脚本里对 update 单独容错。2.4 查询装之前先看清楚装之后也要能查回来查询命令我用得比安装命令还频繁因为它能回答这个东西到底存不存在、从哪来、会带进来什么。apt-cache search keyword # 按关键词搜包 apt-cache show pkg # 看包的完整元信息 apt-cache policy pkg # 看候选版本和各源优先级 apt-cache depends pkg # 看它依赖谁 apt-cache rdepends pkg # 看谁依赖它反查 apt-cache madison pkg # 各源里的版本一览 apt list --installed # 列出已安装的包 dpkg -l pkg # 已安装包的详细状态 dpkg -L pkg # 这个包装了哪些文件 dpkg -S /path/to/file # 这个文件属于哪个包apt-cache policy是我最常用的一个。当你遇到为什么装的是这个版本而不是那个版本时它能直接告诉你候选版本号、各个源的优先级、以及是否被 pin 住。输出里的Candidate那一行就是最终会装的版本。dpkg -S反查文件归属也很实用。比如某个配置文件不知道被哪个包装进来的或者报错信息里提到一个陌生路径直接dpkg -S一查就知道来历。apt-cache depends和rdepends在卸载前特别值得跑一遍。rdepends能告诉你谁还依赖着我要删的这个包如果输出里有一堆你不想动的包那这次卸载就得重新考虑方案改用apt-mark hold或者降级处理而不是硬删。3. 从零到跑通一台干净机器的完整实操流程把前面这些命令串起来才是真正能用的流程。这一节我跑一遍从刚装完系统到装好一个服务端软件的完整链路每一步说清楚为什么这么做。3.1 第一步先确认源配置再决定要不要换拿到一台新机器第一件事不是 install而是看源。cat /etc/apt/sources.list ls /etc/apt/sources.list.d/ cat /etc/apt/sources.list.d/*.sources 2/dev/null关心两件事源地址能不能通、组件全不全。Ubuntu 默认源里的main restricted universe multiverse四个组件含义不同main是官方支持的自由软件universe是社区维护的自由软件multiverse是受法律或版权限制的软件。很多无法定位软件包其实就是因为只启用了main而目标包在universe里。换源这件事只在默认源确实慢的情况下才做国内常见的选择是各家云厂商和高校提供的镜像站。替换前先备份sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak换完源后必须跑一次sudo apt-get update否则索引还是旧的换源等于没换。注意源配置和密钥是配套的。只改地址不更新密钥会出现签名验证失败。deb822 格式里的Signed-By字段就是干这个的不要随手删掉。3.2 系统更新的正确顺序和参数取舍源确认无误之后更新流程是固定的三步sudo apt-get update # 拉索引 sudo apt-get -s upgrade # 模拟看要升多少 sudo apt-get upgrade -y # 实跑 sudo apt-get autoremove # 清理孤立包跳过模拟这一步是我见过最常见的翻车原因。有些升级会牵连到内核、grub、显卡驱动装完之后必须重启不重启就会出现各种诡异现象比如驱动版本和内核模块对不上导致图形界面起不来。所以在跑升级之前先看模拟输出里有没有linux-image-*、nvidia-*、grub-*这类包。涉及内核升级时我的顺序是apt-get updateapt-get upgrade或dist-upgrade看情况检查/var/run/reboot-required是否存在若存在择机重启重启前确认当前内核有可用的备用项test -f /var/run/reboot-required echo 需要重启 ls /boot/vmlinuz-*提示跑dist-upgrade之前建议先确认/boot分区剩余空间。内核包不大但/boot常常单独分区且只有几百兆空间不够会导致 dpkg 配置阶段失败进而整个 apt 卡在半死不活的状态。3.3 装一个服务端软件以 openssh-server 为例这个包几乎是每台服务器都会装的正好拿它跑一遍完整的安装链路。# 1. 确认包存在且看来源 apt-cache policy openssh-server # 2. 模拟安装 sudo apt-get -s install openssh-server # 3. 实际安装跳过推荐包 sudo apt-get install -y --no-install-recommends openssh-server # 4. 确认服务状态 systemctl status ssh ss -tlnp | grep :22 # 5. 确认装了哪些文件 dpkg -L openssh-server | head -30这里重点说--no-install-recommends。apt 把依赖分成两档Depends必须满足不满足装不了和Recommends强烈建议默认会装但可以跳过。Suggests则默认不装。对于服务器场景跳过 Recommends 能显著减少装进来的包数量攻击面也更小。比如装openssh-server时如果不跳过可能会带进一些文档和辅助工具对于精简镜像来说是不必要的。当然跳过 Recommends 也有风险某些软件的功能依赖推荐包跳过后会出现能启动但某个功能不可用的情况。所以我的做法是服务器、容器、精简镜像一律跳过桌面环境和个人机器保持默认。如果装完之后服务起不来第一件事是看日志而不是重装journalctl -u ssh -n 50 --no-pager3.4 卸载与善后的组合拳卸载一个软件完整的动作是四步缺一步就会留垃圾# 1. 停服务、禁用开机自启如果服务还在跑 sudo systemctl stop nginx sudo systemctl disable nginx # 2. purge 主包及其配置 sudo apt-get purge -y nginx nginx-common # 3. 清理孤立依赖 sudo apt-get autoremove --purge -y # 4. 清理下载缓存 sudo apt-get cleanapt-get clean清的是/var/cache/apt/archives下的 deb 文件autoclean只清过期版本。在一个长期运行的机器上这个目录攒到几个 G 是很正常的事。查一下大小du -sh /var/cache/apt/archives这里有个经验如果要卸载的东西和系统基础组件沾边先跑apt-cache rdepends看反查结果。我曾经见过有人为了腾空间 purge 掉一个看起来没用的库结果连带一堆桌面组件被 autoremove 干掉图形界面直接进不去。反查结果里出现ubuntu-desktop、gnome-shell这类元包时就该停手了。3.5 把包装到别处apt-get download 与离线部署内网机器、隔离环境、批量装机都用得上离线包方案。完整流程是# 在联网机器上把整棵依赖树下载到指定目录 mkdir -p /tmp/offline-debs sudo apt-get -o Dir::Cache::archives/tmp/offline-debs \ install --download-only -y --reinstall openssh-server # 打包拷走 tar czf offline-debs.tar.gz -C /tmp/offline-debs . # 在目标机器上解包并安装 tar xzf offline-debs.tar.gz -C /tmp/offline-debs sudo dpkg -i /tmp/offline-debs/*.deb # 如果有依赖没满足用这条兜底 sudo apt-get -f install -y--reinstall在这里的作用是强制重新下载否则对于已经装过的包apt 会认为不需要下载导致下载目录是空的。这个细节坑过不少人。apt-get download则是另一个场景——你只想要一个 deb 文件比如拿它去解包看里面的文件、或者给一台不能装的机器做参考apt-get download nginx dpkg-deb -c nginx_*.deb | head # 查看包内容不解压 dpkg-deb -x nginx_*.deb /tmp/x # 解压到指定目录dpkg-deb -c这个用法我经常用来确认一个包到底会往哪写文件装之前先看一眼心里有底。4. 高频报错排查实录无法定位软件包、锁冲突、脚本报错前面讲的是顺风局这一节全是逆风局。报错信息本身往往很模糊但只要理解成因排查路径其实是固定的。4.1 无法定位软件包的六种成因与逐条验证这个报错信息出现频率极高成因至少有六种按出现概率排序第一种索引没更新。这是最简单的先跑sudo apt-get update。第二种包不在启用的组件里。用apt-cache search搜不到但你知道它存在就去检查源的Components有没有包含universe或multiverse。第三种源地址里没有这个包。典型代表就是ros-noetic-desktop-full。这个包不在 Ubuntu 官方源里必须先添加 ROS 的源并导入密钥sudo apt-get install -y software-properties-common sudo add-apt-repository universe sudo apt-get update # 添加 ROS 源以 Noetic / Ubuntu 20.04 为例 sudo sh -c echo deb http://packages.ros.org/ros/ubuntu focal main /etc/apt/sources.list.d/ros1-latest.list # 导入密钥 curl -sSL http://packages.ros.org/ros.key | sudo apt-key add - sudo apt-get update sudo apt-get install -y ros-noetic-desktop-full顺序很关键加源 → 导密钥 → 再 update。漏掉 update 或者顺序反了都会继续报无法定位。第四种包的架构不支持。比如你在 arm64 上找只有 amd64 的包。用dpkg --print-architecture看当前架构用apt-cache policy看候选项是否为空。第五种包名拼写或者已经被上游移除。fcitx-googlepinyin就是典型。它在 Ubuntu 22.04 之后从仓库里消失了因为上游停止维护。这时候报无法定位是正常的正确做法是换到fcitx5体系和新的中文输入方案而不是继续死磕这个名字。强行去找旧版本的 deb 装上去往往会因为依赖链断裂而失败。第六种pin 优先级把候选版本压掉了。用apt-cache policy pkg看如果Candidate显示为(none)说明有 pin 规则或者 hold 挡住了。去/etc/apt/preferences.d/和apt-mark showhold里找。排查顺序建议先 update → 再 search → 再 policy → 最后查源和架构。这个顺序能覆盖九成以上的情况。4.2 锁文件冲突与 dpkg 中断的收尾报错长这样E: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 12345意思是另一个 apt 或 dpkg 进程正在跑。正确做法是等它结束或者确认它真的死了再清理。粗暴地rm锁文件然后继续操作是数据损坏的经典来源。# 先看是不是真的有进程在跑 ps aux | grep -E apt|dpkg | grep -v grep # 确认进程已经不存在了再清锁 sudo rm /var/lib/dpkg/lock-frontend sudo rm /var/lib/dpkg/lock sudo rm /var/cache/apt/archives/lock sudo dpkg --configure -a最后那句dpkg --configure -a是关键它会继续完成所有被中断的配置步骤。清理锁之后一定要跑它否则数据库状态和实际文件状态会对不上后面装什么都报错。如果系统被强杀在装包中途可能会出现状态更混乱的情况。这时候的抢救顺序是sudo dpkg --configure -a sudo apt-get -f install sudo apt-get update sudo apt-get dist-upgrade4.3 post-installation 脚本返回错误状态怎么处理报错长这样已安装 aic8800d80fdrvpackage 软件包 post-installation 脚本 子进程返回错误状态 1这类错误的特点是包的文件已经拷进去了但配置脚本失败了。dpkg 会把这个包标记为已解包但未配置状态是iFhalf-configured。后续任何 apt 操作都会先尝试重新配置它然后再次失败。排查第一步是找到失败的脚本和它的真实报错# 看具体是哪个脚本 ls /var/lib/dpkg/info/包名.* # 手动跑一遍看真实输出 sudo /var/lib/dpkg/info/包名.postinst configure输出里的真实错误才是关键。常见类型有几种内核模块编译失败dkms 相关的包最常见原因是内核头文件和当前内核不匹配。先确认linux-headers-$(uname -r)装没装。服务启动失败postinst 脚本里执行了systemctl start服务起不来就返回非零。用journalctl -u 服务名看原因。依赖的外部命令不存在脚本里用了某个命令但没装。如果确认这个包就是装不上、也不需要最干净的收尾是把它彻底移除sudo dpkg --remove --force-remove-reinstreq 包名 sudo apt-get autoremove --purge -y注意--force-remove-reinstreq是强制移除一个处于安装失败状态的包。它绕过了正常的一致性检查只在确认这个包不要了的时候用不要当成万能解药。用完立刻跑一次sudo apt-get -f install把依赖关系重新理顺。4.4 依赖地狱从 fix-broken 到手动 hold依赖问题的典型表现是 dpkg 装本地 deb 时报依赖关系不满足或者 apt 报有未能满足的依赖关系。标准处理动作是sudo apt-get -f install它会让 apt 自己去算怎么补上缺失的依赖。如果它给出的方案是删除一大堆包那就得停下来看清楚别直接加-y。另一种场景是版本冲突你装了 A 的 2.0 版本但 B 要求 A 的 1.x。apt 默认不会自动降级会直接报冲突。这时候的选项有两个# 方案一指定版本安装 apt-cache madison pkgA # 看有哪些版本可选 sudo apt-get install pkgA1.2.3-1 # 方案二用 pin 让 apt 优先选低版本 sudo tee /etc/apt/preferences.d/pin-pkgA EOF Package: pkgA Pin: version 1.2.3-1 Pin-Priority: 1001 EOFPin-Priority大于 1000 表示允许降级到这个版本。这个机制在控制内核版本、显卡驱动版本时特别有用。5. 生产环境里的进阶用法与踩坑经验前面四节覆盖了日常操作的绝大部分。这一节讲的是长期运维里才会遇到的问题也是在真实环境里价值最高的部分。5.1 版本锁定hold、apt-mark 与避免意外的升级生产环境最怕的是某次例行更新把关键组件升崩了。控制手段就是apt-mark holdsudo apt-mark hold nginx # 锁定不参与升级 sudo apt-mark showhold # 查看当前所有锁 sudo apt-mark unhold nginx # 解除锁定典型用法是锁住内核和驱动。比如一台跑着特定版本 NVIDIA 驱动的训练机驱动一升级CUDA 版本可能跟着变整个训练环境就废了。这时候sudo apt-mark hold linux-image-generic linux-headers-generic sudo apt-mark hold nvidia-driver-535锁住之后apt-get upgrade会自动跳过这些包但注意如果它们的升级是其他包升级的前置条件upgrade会把相关包也一起保留这时候就要靠dist-upgrade加手动判断了。还有一种更细粒度的控制是 pin它能针对具体版本而不是整个包Package: nginx Pin: version 1.24.* Pin-Priority: 1001这条规则的意思是优先选 1.24 系列并允许降级。比 hold 灵活适合需要长期停留在某个小版本线上的场景。5.2 内核与驱动升级最容易出事故的一类操作内核升级的风险点集中在/boot空间和 grub 配置两处。前面提过/boot空间不足会导致配置阶段失败而 grub 配置失败则可能导致机器重启后进不了系统。我的习惯是每次内核升级后做三件事# 1. 确认新内核的 initrd 生成了 ls -lh /boot/initrd.img-$(ls /boot/vmlinuz-* | tail -1 | sed s|/boot/vmlinuz-||) # 2. 确认 grub 配置里能看到新内核 grep -c menuentry /boot/grub/grub.cfg # 3. 确认旧内核还在留着做退路 dpkg -l | grep ^ii linux-image保持至少两个可启动内核是成本最低的保险。自动清理旧内核的配置可以关掉# 修改 /etc/apt/apt.conf.d/01autoremove-kernels 或对应策略文件对于显卡驱动尤其是需要 CUDA 的场景更稳妥的路径是先确认目标 CUDA 版本要求的驱动大版本再用 pin 锁住驱动版本而不是让 apt 每次自动升到最新。5.3 空间不够清理、扩容与嵌入式场景的差异apt-get报空间不足时清理的顺序是sudo apt-get clean # 清空下载缓存 sudo apt-get autoremove --purge -y # 清孤立包 sudo journalctl --vacuum-size200M # 清日志日志常常比包缓存还大 du -sh /var/cache/apt /var/log /var/lib/apt在很多嵌入式设备上情况不太一样。它们用的往往不是 apt 而是opkg包管理器不同、仓库更小、存储空间以兆计。这类设备上装不上最常见的原因不是源配置而是可写的 overlay 空间已经满了。处理思路是先看挂载点和剩余空间清理临时文件和日志再考虑把 overlay 扩到外部存储上。命令不一样但底层逻辑和 apt 是相通的先确认源、再确认空间、最后确认依赖。这三步在任何包管理器上都成立。5.4 把更新做成自动化缓存与无人值守的取舍机器多了之后每台都去公网拉包是不现实的。标准做法是在内网架一个 apt 缓存代理比如apt-cacher-ng各机器把源指向它第一次拉取的包会被缓存下来后续机器直接命中缓存。无人值守更新的配置在/etc/apt/apt.conf.d/20auto-upgradesAPT::Periodic::Update-Package-Lists 1; APT::Periodic::Unattended-Upgrade 1;我的建议是分开对待安全补丁可以自动装内核和驱动一定不要自动装。实现方式是在50unattended-upgrades里用黑名单排除掉内核和驱动相关的包Unattended-Upgrade::Package-Blacklist { linux-image-; linux-headers-; nvidia-; };理由很直接安全补丁出问题的概率低、重启后基本无感内核和驱动出问题的概率高而且往往需要重启才能暴露无人值守场景下你根本来不及反应。6. 我常用的命令速查表与参数备忘录最后一节把前面散落的命令收拢成两张表方便直接查。6.1 日常操作速查表目标命令备注更新索引apt-get update只更新索引不改系统查看可升级项apt list --upgradable或apt-get -s upgrade安全升级apt-get upgrade不删包、不装新包完整升级apt-get dist-upgrade允许装新包、删旧包安装apt-get install pkg加-y用于脚本精简安装apt-get install --no-install-recommends pkg服务器推荐重装apt-get install --reinstall pkg修复被改坏的文件只下载apt-get download pkg不安装到当前目录整树下载apt-get install --download-only pkg到 apt 缓存目录卸载apt-get remove pkg保留配置彻底卸载apt-get purge pkg连配置一起删清孤立包apt-get autoremove --purge执行前看删除列表清下载缓存apt-get clean释放/var/cache/apt修复依赖apt-get -f installdpkg -i 之后的兜底完成中断配置dpkg --configure -a清锁之后必跑6.2 几个最容易记混的参数对照-s和-y-s是模拟什么都不做只输出计划-y是自动回答 yes 开始执行。新手常把-s当成-y的简写结果敲了半天什么都没发生。remove和purge前者留配置后者不留。重装排障时要选对选错了白折腾。update和upgrade前者只动索引后者动系统。这两个字面上只差几个字母语义差很远。--no-install-recommends和--install-suggests一个减、一个加。默认行为在两者之间只装 Recommends。apt-mark hold和 pin前者按包锁后者能按版本锁并且支持优先级。简单的用 hold复杂的用 pin。再补一个查询类的组合拳遇到这东西从哪来的问题时基本能一次查清pkgnginx apt-cache policy $pkg # 候选版本和来源 apt-cache show $pkg # 完整元信息 apt-cache depends $pkg # 依赖谁 apt-cache rdepends $pkg # 谁依赖它 dpkg -L $pkg # 装了哪些文件我个人在实际运维里的体会是apt-get真正容易出问题的从来不是命令本身而是源、空间、锁、状态这四个东西。命令记不住可以查但这四样出问题时系统往往已经处于半残状态了。所以我现在养成的习惯是动手前先apt-cache policy看一眼来源升级前先-s跑一遍模拟清理前先du -sh看一眼空间卸载前先rdepends看一眼牵连。这四步加起来不到一分钟能省掉的返工时间是以小时计的。最后分享一个小技巧如果你不确定某个操作到底会做什么就把命令里的apt-get换成apt-get -s它会完整告诉你计划里要装什么、删什么、升什么而不会真的动手。这个习惯我保持了几年救过好几次生产环境。
返回列表