服务器运维

apt-get 命令详解:update、install、remove 与 apt 的区别

apt-get 是 Debian 和 Ubuntu 上安装、升级、卸载 .deb 软件包的命令行工具。最常用的组合是先 apt-get update 刷新软件包列表,再 apt-get install 安装;卸载用 remove(保留配置)或 purge(连配置一起删)。apt 与 apt-get 用的是同一套引擎,交互操作用 apt 更顺手,脚本里用 apt-get 更稳妥。

作者 顶联产品团队发布于 7 分钟阅读

apt-get 是 Debian 系发行版(Debian、Ubuntu 及其衍生版)的软件包管理命令,属于 APT 工具集。它负责从软件源下载 .deb 包、自动处理依赖,再交给底层的 dpkg 完成安装和卸载。日常用法就三步:先刷新软件包列表,再安装或卸载。

sudo apt-get update                 # 刷新软件包列表,不会升级任何软件
sudo apt-get install -y nginx       # 安装 nginx 及其依赖,-y 表示自动确认
sudo apt-get remove nginx           # 卸载程序,/etc/nginx 下的配置保留

子命令对照表:update、upgrade、install、remove 各做什么

命令 作用 会装新包吗 会删包吗 典型场景
update 从软件源下载最新的软件包列表,不升级任何软件 否 否 每次安装、升级之前
upgrade 把已安装的包升级到列表里的新版本 否,需要新依赖的包会被“保留”不升级 否 日常打安全补丁
dist-upgrade 在 upgrade 的基础上处理依赖变化,需要时装新包、删冲突的包 是 是 内核升级、依赖关系变化
install 包名 安装或升级指定的包及其依赖 是 很少,只在冲突时 装软件
install -f 修复依赖关系不完整的系统(--fix-broken) 是 可能 dpkg 装包后缺依赖
install --reinstall 包名 重新安装同一版本 否 否 程序文件被误删或改坏
remove 包名 卸载,保留配置文件 否 是 暂时不用,以后可能再装
purge 包名 卸载,并删除配置文件 否 是 彻底不要了,或想恢复默认配置重装
autoremove 删除当初作为依赖自动装上、现在已经没有包需要的软件 否 是 卸载软件之后、清理旧内核
download 包名 只把 .deb 下载到当前目录,不安装,不下载依赖 否 否 离线安装、查看包里有什么
clean / autoclean 清空 /var/cache/apt/archives 里下载过的 .deb;autoclean 只删已经无法再下载的旧版本 否 否 释放磁盘空间

几个常用的全局参数:-y 自动回答 yes;-s 只模拟、不真正执行,用来预先看会发生什么;-q 减少输出,适合写进日志;--no-install-recommends 只装必需的依赖,不装“推荐”的附带软件,服务器上用它能少装不少东西。

upgrade 和 dist-upgrade 的区别

在 Ubuntu 上执行 apt-get upgrade,经常看到这样的输出:

The following packages have been kept back:
  linux-generic linux-headers-generic linux-image-generic
0 upgraded, 0 newly installed, 0 to remove and 3 not upgraded.

原因是新内核要以一个新的包名(包名里带着新的版本号)安装进来,而 upgrade 的规则是绝不装新包、绝不删包,只能把这几个元包“保留”在原版本。dist-upgrade 没有这个限制,会把新内核装上;直接 apt-get install linux-generic 也能达到同样的效果。Ubuntu 还有分阶段推送(phased updates)机制,部分更新会先推给一部分机器,没轮到的机器上这些包也会显示为暂不升级,过几天自然会升级,不必处理。

因为 dist-upgrade 会删包,执行前先模拟一遍,看看要删的是什么:

apt-get -s dist-upgrade | grep '^Remv'     # 模拟执行,只列出将被删除的包

另一个常见误解:名字里有 dist,但 dist-upgrade 不会把 Ubuntu 22.04 升到 24.04,它只在当前软件源的范围内升级。跨大版本升级,Ubuntu 用 do-release-upgrade,Debian 按对应版本发行说明里的步骤先改软件源再升级。

apt 和 apt-get 的区别

apt 是 APT 1.0(2014 年)起加入的命令,把 apt-get 和 apt-cache 里最常用的功能合到一起,并改进了交互体验。两者底层是同一个库、同一份软件源配置、同一个下载缓存和同一个 dpkg 数据库:用 apt 装的包,可以用 apt-get 卸载,反过来也一样。

对比项 apt apt-get
面向谁 在终端里手动操作的人 脚本和自动化工具
输出 有进度条和颜色,update 后提示有多少包可以升级 纯文本,格式多年保持稳定
在脚本里使用 输出被重定向时会打印 WARNING: apt does not have a stable CLI interface. Use with caution in scripts. 没有这类警告
upgrade 的行为 apt upgrade 需要时会安装新的依赖包,但仍然不删包 apt-get upgrade 不装新包
下载的 .deb 默认在安装成功后删除 保留在 /var/cache/apt/archives
查询 apt search、apt show、apt list --installed、apt list --upgradable 查询要用 apt-cache search、apt-cache show、apt-cache policy
对应关系 apt full-upgrade apt-get dist-upgrade

选择很简单:自己登录上去装个软件、看看有什么可升级,用 apt;写进初始化脚本、定时任务、自动化工具里的,用 apt-get,它的参数和输出格式不会随版本变来变去,脚本解析起来更可靠。

安装软件:指定版本、本地 .deb 与 install -f

先看清楚要装的是哪个版本、来自哪个源:

apt-cache policy nginx        # Installed 是已装版本,Candidate 是将要安装的版本,下面列出各个来源
apt-cache madison nginx       # 列出软件源里所有可装的版本

需要固定版本时,在包名后面加 =版本号,版本号照 madison 输出的第二列原样填写,然后锁定,防止下次升级被顺手升上去:

sudo apt-get install nginx=1.24.0-2ubuntu7   # 示例版本号,以 madison 的实际输出为准
sudo apt-mark hold nginx      # 锁定,upgrade 时跳过它
apt-mark showhold             # 查看哪些包被锁定
sudo apt-mark unhold nginx    # 解除锁定

厂商单独提供的 .deb(监控 agent、阵列卡管理工具之类)有两种装法。用 dpkg 装,它不管依赖,缺什么就报错,留下一个“装了一半”的包:

sudo dpkg -i ./agent_2.1.0_amd64.deb
# 缺依赖时报 dependency problems prevent configuration of agent
sudo apt-get install -f       # 补装缺失的依赖,并完成这个包的配置

更省事的做法是直接让 apt-get 装本地文件,依赖一并解决。注意路径要带 ./ 或写成绝对路径,否则 apt-get 会把它当成软件源里的包名去找:

sudo apt-get install ./agent_2.1.0_amd64.deb

apt-get install -f 不是万能的。它的目标是让依赖关系恢复一致,如果某个包需要的依赖在当前系统上根本装不上(比如 .deb 是给别的发行版版本打的),它给出的“修复”方案就是把这个包,甚至别的包一起删掉。按 Y 之前,一定看清 The following packages will be REMOVED 下面列了什么。

卸载与清理:remove、purge、autoremove 的区别

以 nginx 为例走一遍:

sudo apt-get remove nginx                # 删程序,/etc/nginx 还在
dpkg -l | grep '^rc'                     # 列出“已卸载但配置还在”的包
sudo apt-get purge nginx nginx-common    # 连配置一起删
sudo apt-get autoremove --purge          # 顺带删掉当初自动装上、现在没人需要的依赖

dpkg -l 第一列的 rc 表示期望状态是删除(r),当前只剩配置文件(c)。一次性清掉所有残留配置:

dpkg -l | awk '/^rc/ {print $2}' | xargs -r sudo apt-get purge -y

三点要注意:

  • purge 只删包管理器登记过的文件,网站目录、上传文件这类你自己放进去的内容不会删。部分数据库软件包在 purge 时会询问是否删除数据目录,看清再回答。
  • autoremove 依据的是“自动安装”标记。依赖包装上时被标记为 auto,不再被任何包需要时就会被 autoremove 删掉。某个依赖你想单独留着,执行 apt-mark manual 包名 改成手动安装;apt-mark showauto 能看到全部自动安装的包。卸载一个元包(比如桌面环境的总包)之后,autoremove 可能列出一大串要删的软件,先加 -s 模拟再决定。
  • 旧内核也靠 autoremove 清理。APT 会自动保护正在运行的内核和最新的内核不被删除,更早的旧内核会出现在 autoremove 的列表里。/boot 分区不大的机器,内核升级几次后可能装不下新内核,定期执行一次即可,不要手工删 /boot 里的文件。

下载缓存默认留在 /var/cache/apt/archives,用 du -sh /var/cache/apt/archives 看占了多少,apt-get clean 全部清掉,以后需要时会重新下载。

apt-get download 与离线安装

apt-get download 包名 把 .deb 下载到当前目录,不需要 root,也不会安装。单独拿一个包时很方便,比如想看看包里有哪些文件:

apt-get download ipmitool
dpkg -c ipmitool_*.deb        # 列出包内文件
dpkg -x ipmitool_*.deb ./x    # 解包到 ./x 目录,不安装

它不带依赖,给没有外网的服务器准备安装包时,要把依赖一起下载。在一台能上网、发行版版本和 CPU 架构都与目标机相同的机器上执行:

mkdir ipmitool-debs && cd ipmitool-debs
apt-get download $(apt-cache depends --recurse --no-recommends --no-suggests \
  --no-conflicts --no-breaks --no-replaces --no-enhances ipmitool | grep '^\w' | sort -u)

这样会把整条依赖链都下载下来,其中不少目标机上已经装了,安装时同版本的包会被跳过。如果报 Can't select candidate version from package ... as it has no candidate,说明列表里混进了虚拟包名(如 debconf-2.0),它没有对应的 .deb,把这个名字从列表里去掉再下载即可。把目录拷到目标机后安装:

sudo apt-get install ./*.deb

版本必须对应:给 Ubuntu 24.04 准备的包,就要在 24.04 上下载,混用版本是离线安装失败最常见的原因。机房里要维护的机器一多,与其每次手工搬包,不如在内网放一台 apt-cacher-ng 做缓存代理(默认端口 3142),各服务器在 /etc/apt/apt.conf.d/ 下新建一个文件,写入 Acquire::http::Proxy "http://10.10.0.5:3142";,同一个包只从外网下载一次。软件源地址是 https 的,缓存需要另外配置,以 apt-cacher-ng 文档为准。

服务器上常见的 apt-get 报错

报错 原因 处理
E: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 1234 (unattended-upgr) 另一个 apt 或 dpkg 进程正在运行;Ubuntu 刚开机时常是自动安全更新 等它结束,用 ps -fp 1234 看是什么进程。不要删锁文件,apt 自己也会提示 removing the lock file is not a solution
E: dpkg was interrupted, you must manually run 'sudo dpkg --configure -a' to correct the problem. 上次安装或升级中途断了,比如 SSH 断线、进程被杀 照提示执行 sudo dpkg --configure -a,再执行 sudo apt-get install -f
E: Unable to locate package ipmitools 没有 update、包名写错(这里多打了一个 s),或者包所在的组件(如 Ubuntu 的 universe)没有启用 apt-get update 后用 apt-cache search 关键词 找正确的包名;启用 universe:sudo add-apt-repository universe
The following packages have unmet dependencies 和 you have held broken packages 第三方源的包与当前系统版本不匹配,或有包被 hold apt-cache policy 包名 看候选版本来自哪个源;apt-mark showhold 看锁定的包
You might want to run 'apt --fix-broken install' to correct these. 系统里已经有依赖不完整的包,之后的安装都会被拦住 执行 sudo apt-get install -f,看清要删除的包再确认

在远程服务器上做大批量升级,放在 tmux 或 screen 里执行,SSH 断了升级也不会被打断,这是避免出现第二行报错最简单的办法。写进脚本时,用下面的写法避免升级卡在交互提问上:

export DEBIAN_FRONTEND=noninteractive
apt-get update -q
apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade

DEBIAN_FRONTEND=noninteractive 让安装脚本不弹出配置对话框;--force-confdef 和 --force-confold 合起来的意思是:新包带来的配置文件与你改过的版本冲突时,有默认处理方式就按默认处理,否则保留你现有的配置,不会被新版本覆盖。

升级内核后起不来:在机房里怎么兜底

dist-upgrade 装上新内核,重启后卡住或网卡不认,是批量升级时最怕遇到的情况。这时 SSH 已经连不上,只能从带外进去:在 Toplink DCIM 的 IPMI 远程管理里打开走 BMC 通道的 VNC 控制台,重启时调出 GRUB 菜单。Ubuntu Server 默认隐藏这个菜单,UEFI 启动的机器在启动时按 Esc,传统 BIOS 启动的按住 Shift,进入 Advanced options for Ubuntu 选上一个内核启动。进系统后先把问题内核卸掉,或用 apt-mark hold 暂缓升级,查清原因再处理。

如果系统连旧内核也进不去,租用服务器的客户可以在客户自助端切到救援模式,挂载原来的系统盘,用 chroot 进入后执行 dpkg --configure -a 或重装内核包,硬盘上的数据不受影响。批量升级前先挑一两台做验证,确认重启正常再全面铺开,比事后救火省事得多。

常见问题

apt-get 一定要用 root 执行吗?

会改动系统的子命令(update、install、remove、upgrade、clean 等)需要 root 或 sudo。apt-get download、加 -s 的模拟执行,以及 apt-cache 的各种查询,普通用户就能运行。

怎么查一个命令属于哪个软件包?

已经装上的,用 dpkg -S 加命令的完整路径,例如 dpkg -S /usr/bin/ipmitool;还没装的,先 apt-get install apt-file,执行 apt-file update 后用 apt-file search bin/命令名 查找。Ubuntu 上直接输入一个没装的命令,通常也会提示该装哪个包。

/etc/apt/sources.list 里只剩注释,软件源配在哪里?

Ubuntu 24.04 起默认改用 deb822 格式,软件源写在 /etc/apt/sources.list.d/ubuntu.sources 里,一个源是一段 Types、URIs、Suites、Components 字段。换镜像就改这个文件的 URIs 行,改完执行 apt-get update。

想看看在你的机房里怎么用?

从一次产品演示开始,梳理你的业务链路。

查看价格
服务热线 400-112-2951

让我们聊聊你的 IDC 业务

扫码添加企业微信,预约产品演示或申请试用。

Toplink 企业微信二维码

长按保存或使用企业微信 / 微信扫描

也可致电
400-112-2951
Telegram
@TopLink88