上周帮同事收拾一台跑了两年多的 Ubuntu 20.04 工作站,症状特别典型:他只是想装个看 PDF 的小工具,结果点左上角那个软件中心图标,转了两圈就没了;再右键一看,启动器里的图标干脆不翼而飞。打开终端敲snap list,输出里连snap-store的影子都没有——这基本可以断定,不是软件中心坏了,是它被人"清理"掉了。
Linux 系统里的软件安装和软件中心恢复,看着是两件事,实际上是一根藤上的两个瓜。Ubuntu 20.04(代号 Focal Fossa,2020 年 4 月发布的 LTS 长期支持版本,最后一个点版本是 20.04.6)从这一代开始,把图形化软件中心整个换成了 Snap 打包的应用,这直接导致了很多老教程里的修复方法失效——你按网上的方法apt install gnome-software,图标还是不出现,因为真正撑起"Ubuntu Software"这个门面的,根本不是那个 deb 包。这篇文章就围绕 Ubuntu 20.04 的软件安装体系、包管理器分工、以及软件中心消失后的完整恢复链路来讲,适合刚接触 Linux 的新手,也适合被这个问题卡了半天、查了一圈教程越修越乱的老用户。
1. Ubuntu 20.04 装软件这件事,先把三个包管理器分清楚
很多人装软件时的困惑,本质上是没搞清楚 Ubuntu 里同时跑着几套互不相同的软件分发体系。你在终端敲的每一行安装命令,背后走的是完全不同的仓库、不同的依赖解析器、不同的卸载逻辑。分不清这三者,"装不上"和"卸不干净"就会反复出现。
1.1 apt、dpkg、snap 各自管什么
先给一个最直观的定位:
| 工具 | 层级 | 依赖处理 | 典型仓库 | 卸载是否干净 |
|---|---|---|---|---|
| dpkg | 底层 | 不处理,只管解包安装 | 无,直接操作 deb 文件 | 一般 |
| apt | dpkg 的上层封装 | 自动解析并补齐依赖 | 官方源、PPA、第三方源 | 较干净 |
| snap | 完全独立的体系 | 依赖打包在应用内部 | Snap Store | 很干净,但占空间 |
dpkg是 Debian 系最底层的包管理工具,它只做一件事:把一个.deb文件里的内容铺到文件系统上,然后登记到数据库里。它不知道你要装的软件依赖什么,也懒得管——依赖缺失时它会直接把错误甩给你,让你自己想办法。
apt是站在dpkg肩膀上的调度器。它先去读/etc/apt/sources.list和/etc/apt/sources.list.d/下面的仓库索引,算出一套能满足依赖的安装顺序,再挨个调用dpkg落地。这也是为什么apt报错时经常提示你跑一下apt --fix-broken install——它知道数据库里有个"半装"的状态需要收尾。
snap是另一条完全平行的路。它把应用和它需要的运行库、语言运行时全部塞进一个压缩镜像里,挂载到/snap目录下运行,理论上跟系统里其他部分互不干扰。代价是每个 snap 应用动辄几百兆,启动时还要挂载,第一次打开会比 apt 装的程序慢一些。Ubuntu 20.04 的软件中心snap-store本身就是个 snap 应用,这一点后面还要重点讲。
1.2 一个真实场景:同一个软件,三条安装路径的差别
假设你要装一个代码编辑器,三条路都能走通,但体验完全不同。
走apt,命令是sudo apt install 包名,装完文件散落在/usr/bin、/usr/share等处,体积小,启动快,但版本通常比较老——官方源里冻结的版本,可能比上游落后一两年。
走snap,命令是sudo snap install 包名,装完在/snap/bin/下有软链接,版本永远是最新的,自动更新不用你管,但占用空间大,而且因为是沙箱运行,访问你 home 目录之外的文件、调用系统里的某些硬件接口,可能会被权限挡住,需要手动sudo snap connect授权。
走第三方 deb 或者源码编译,版本最新、可控性最强,但升级和卸载全靠你自己记着,时间一长就是个隐形维护负担。
我的建议很简单:系统工具和基础库走 apt,桌面应用和需要新版本的开发工具走 snap,实在没有才考虑第三方 deb。这个顺序能让你在 90% 的场景里少踩坑。
顺带说一句版本确认,动手之前先看清楚自己在哪个系统上:lsb_release -a会输出发行版和代号,cat /etc/os-release能看到更详细的构建信息。这一步很有必要——网上大量教程是针对 18.04 甚至 16.04 写的,照搬到 20.04 上,软件中心的修复方法第一个就不对。
2. 把 apt 用顺:镜像、更新、安装与卸载的完整动作
apt是日常使用频率最高的工具,但真正用明白的人不多。大部分人的使用习惯停留在"装东西敲 install,卸载敲 remove",遇到报错就上网搜一条命令复制粘贴,结果问题越滚越大。
2.1 换国内镜像源:sources.list 的改法与验证
默认的官方源在国内访问速度经常慢到让人怀疑网络断了,apt update卡在 "Waiting for headers" 十几分钟是常事。换成国内镜像是最有效的提速手段,清华、中科大、阿里云这些镜像站都是长期稳定运行的开源镜像,直接改配置即可。
动手前先备份,这一步别省:
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak然后确认当前系统的代号,20.04 的代号是focal:
lsb_release -cs输出的focal就是你要在源地址里用的字段。不要想当然地写20.04,仓库路径用的是代号不是版本号,写错了apt update会直接报 404。
一个可用的 20.04 源配置长这样(这里以清华镜像为例):
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse改完之后跑一次sudo apt update,观察是否有Err或404。如果出现Release file ... is not valid yet,八成是系统时间不对,跟镜像服务器的时间差超过允许范围了,用timedatectl看一眼,必要时开一下自动校时。
提示:改源之前如果不确定,先把
sources.list整体备份,出问题直接sudo cp回去。见过太多人改坏之后连原始内容都找不回来。
2.2 apt update / install / remove / purge 的区别与常用参数
这几个子命令的语义差别,值得单独拎出来说清楚:
apt update:只刷新本地缓存的仓库索引,不安装也不升级任何东西。换了源之后必须跑。apt upgrade:把已安装的包升级到新版本,不会删除任何已有包。如果某个升级需要移除旧包,它会跳过并提示你。apt full-upgrade:允许为完成升级而移除或新增包,比upgrade更彻底。跨版本升级时会用到,日常慎用。apt install 包名:安装。加-y跳过确认,加--reinstall强制重装当前版本。apt remove 包名:卸载程序,但把配置文件留在系统里。apt purge 包名:连配置文件一起清掉。修复软件中心、清除错误配置时,purge 比 remove 更有用。apt autoremove:清理那些当初作为依赖装进来、现在没人需要的包。
排查问题时有两个查询命令特别好用。apt-cache policy 包名会告诉你这个包当前有哪些候选版本、分别来自哪个仓库,当你怀疑某个软件装的是旧版或者来自一个不该存在的第三方源时,这条命令一眼就能看出来。apt list --installed | grep 关键词则用来确认某个包到底装没装、装的是哪个版本。
还有一个冷门但很实用的:dpkg -S /usr/bin/某程序,反查某个可执行文件属于哪个包。清理来路不明的程序时非常管用。
2.3 依赖断裂与锁文件:最常见的两类报错怎么破
apt 报错里出现频率最高的就两类,处理方式完全不同。
第一类是依赖问题,典型输出是"下列软件包有未满足的依赖关系"或者"正在处理用于 xxx 的触发器时出错"。这时候先不要乱删东西,按顺序跑:
sudo apt --fix-broken install sudo dpkg --configure -a sudo apt autoremove--fix-broken会让 apt 尝试补齐缺失的依赖,--configure -a是把数据库里所有处于"解包了但没配置完"状态的包重新配置一遍。九成的依赖断裂问题这两条就能解决。如果还不行,用sudo apt install -f再兜一次底。
第二类是锁文件被占用,报错类似无法获得锁 /var/lib/dpkg/lock-frontend。原因通常是后台还有一个 apt 或 unattended-upgrades 在跑,或者上次安装被 Ctrl+C 强行打断了。
正确处理顺序是:先用ps aux | grep -i apt看看是不是真有进程在运行,有的话等它跑完;确认没有进程后再清理锁文件。不要一看到锁就无脑删,如果真的有 apt 在跑,你把锁删了,两个 apt 同时写数据库,后果比等几分钟严重得多。
确认无进程后再执行:
sudo rm /var/lib/dpkg/lock-frontend sudo rm /var/lib/dpkg/lock sudo rm /var/cache/apt/archives/lock sudo dpkg --configure -a3. 不在源里的软件:deb 包、PPA、源码编译与 AppImage
官方源里的软件版本偏保守,很多新工具根本不在里面。这时候就要走扩展渠道,但每一条渠道的成本和风险都不一样,选错了会给以后的系统维护埋雷。
3.1 dpkg 装离线 deb 包以及依赖手到病除的修法
从官网下载的.deb文件,标准装法是:
sudo dpkg -i 软件包.deb但这一步十有八九会报依赖缺失。此时不要慌,也不要一个个手动去装依赖,直接跑:
sudo apt install -fapt 会读数据库里那个"依赖未满足"的记录,自动把缺的包补上,然后再回头配置刚才那个 deb。这个组合拳比任何手动装依赖的方式都省事。
其实还有一个更省心的写法,很多人都不知道:
sudo apt install ./软件包.deb在路径前面加./,apt 会把它当成一个本地包源来处理,安装过程中会自动解析并下载依赖,一步到位,不用再补apt install -f。20.04 上的 apt 版本完全支持这个用法。
卸载的对应命令是sudo dpkg -r 包名,想连配置一起清掉用sudo dpkg -P 包名。
3.2 PPA 与第三方仓库:方便与风险并存
PPA 是个人或团队在 Launchpad 上维护的软件源,加进来之后apt就能直接装到新版本。添加命令是:
sudo add-apt-repository ppa:用户/仓库名 sudo apt update如果提示add-apt-repository: command not found,先装software-properties-common。
PPA 的便利背后有个容易忽略的坑:任何一个 PPA 挂掉或者更新延迟,都会让整个apt update失败,报错信息里会明确写出是哪个源的 Release 文件取不到。这时候其他所有源明明都是好的,但你就是装不了任何东西。解决办法是进/etc/apt/sources.list.d/把对应那个.list文件临时改个后缀名禁用掉,等它恢复再改回来。
另一个经验:同一个软件的 deb 官方源和 PPA 不要同时挂,很容易出现版本冲突,apt-cache policy一看会发现候选版本来源混乱,最后装出来的是哪个谁都说不准。
3.3 源码编译与 AppImage:什么情况下才值得
源码编译的流程大家都熟:./configure && make -j$(nproc) && sudo make install。它的最大问题不是编译慢,而是卸载极其困难——make install把文件撒得到处都是,想删干净基本靠手动回忆。
我的做法是:编译时用--prefix=/usr/local指定安装前缀,如果项目支持make uninstall就用它卸载;不支持的,装之前用checkinstall代替make install,它会顺手打成一个 deb 包,以后卸载就跟普通软件一样了。另外make时加-j$(nproc)可以并行编译,把 CPU 核心吃满,nproc会自动返回当前的核心数,不用自己数。
AppImage 是另一种思路,一个文件就是一个完整应用,不需要安装:
chmod +x 应用.AppImage ./应用.AppImage20.04 上第一次运行 AppImage 常常报 FUSE 相关的错误,装一个libfuse2就好:
sudo apt install libfuse2AppImage 适合那种"偶尔用一下、不想留痕迹"的工具,缺点是每次都要手动去官网下新版,也没有系统级的更新机制。
4. 软件中心不见了?先搞清楚它到底是个什么东西
修东西之前得先知道修的是什么。这一步如果搞错,后面所有操作都是白费力气——我看到过太多人一遍遍重装gnome-software,然后困惑为什么图标还是不出来。
4.1 Ubuntu Software 在 20.04 里是 snap-store,不是普通程序
这是整个问题的关键。Ubuntu 从 20.04 开始,把图形界面上那个叫 "Ubuntu Software" 的软件中心,换成了 Snap 打包的应用,包名就叫snap-store。它本质上是 GNOME 的gnome-software被重新打包塞进了 snap 里,所以你系统里同时存在两个东西:
gnome-software:一个传统的 deb 包,装完在/usr/share/applications/下有个桌面入口。snap-store:一个 snap 包,桌面入口在/var/lib/snapd/desktop/applications/目录下。
在实际的 20.04 桌面上,你点到的那个"软件中心"图标,指向的是snap-store。这就解释了一个经典现象:你sudo apt install --reinstall gnome-software重装半天,图标纹丝不动,因为你根本没碰到出问题的那个组件。
自己动手验证一下就很清楚了:
snap list | grep -i store ls /usr/share/applications | grep -i software ls /var/lib/snapd/desktop/applications | grep -i software如果第一条命令什么都没输出,说明snap-store这个 snap 包已经不在了。
4.2 图标消失的五种表现,对应五种病因
同样是"软件中心打不开",现象不同,根因完全不同。对照下面这张表先定位,比盲目重装高效得多。
| 现象 | 可能病因 | 优先排查方向 |
|---|---|---|
| 启动器里完全找不到图标 | snap-store 被移除,或 snapd 未安装 | snap list是否有输出 |
| 图标在,点了没反应 | snap-store 进程卡死或已崩溃 | ps aux | grep snap-store |
| 图标在,打开后一直转圈 | 网络或 DNS 异常,取不到商店数据 | ping测试域名解析 |
| 打开了但一片空白 | 本地缓存损坏 | 清理 snap-store 缓存目录 |
| 报错"无法连接到 Snap Store" | snapd 服务未运行或系统时间错误 | systemctl status snapd |
还有一种容易被忽略的情况:系统时间不对导致 snap 校验失败。snap 包安装时会做签名验证,如果本机时间跟真实时间偏差过大,验证直接不通过,表现就是 snap 命令各种莫名其妙的失败。排查时顺手敲一句timedatectl,看System clock synchronized是不是yes,不是的话sudo timedatectl set-ntp true打开自动校时。这个坑我在一台长期断电的测试机上踩过,折腾了快一个小时才想到是时间问题。
5. 软件中心恢复实战:一条完整的排查链路
下面这套流程是我自己总结的,从最轻量的操作开始,逐层深入。不要一上来就重装,很多情况重启一下服务就好了,重装反而会丢掉你已经装过的 snap 应用列表。
5.1 第一步:确认 snapd 状态与系统时间
先看服务是否在跑:
systemctl status snapd看到active (running)才算正常。如果是inactive或者failed,先启用并启动:
sudo systemctl enable --now snapd.socket sudo systemctl restart snapd如果snap这个命令本身都不存在,说明 snapd 压根没装或者被卸了:
sudo apt update sudo apt install snapd装完记得重新登录一下会话,让/snap/bin进入 PATH。
接着确认时间:
timedatectl时间不对就sudo timedatectl set-ntp true,等几秒钟再timedatectl复查一次。
5.2 第二步:重装 snap-store 与 gnome-software 插件
服务正常、时间正常,就可以处理组件本身了。先看看当前有哪些 snap 处于异常状态:
snap changes输出里如果有Error状态的记录,说明之前某次操作中断了,先让它自愈:
sudo snap refresh然后处理 snap-store。如果它还在但卡死,先杀掉进程再刷新:
sudo killall snap-store sudo snap refresh snap-store如果它压根不在了,重新装回来:
sudo snap install snap-store如果 snap 体系提示包处于损坏状态,就先移除再装:
sudo snap remove snap-store sudo snap install snap-store至于gnome-software那一侧,也不要完全放着不管——有些场景下系统走的是 deb 版入口,或者你需要 snap 插件来让 deb 版软件中心能显示 snap 应用:
sudo apt install --reinstall gnome-software gnome-software-plugin-snap装完之后刷新桌面数据库,让图标重新注册:
sudo update-desktop-database这一步很多人会漏掉。桌面环境靠.desktop文件的缓存来生成启动器图标,缓存不同步的话,程序明明装好了,图标还是不出现。
5.3 第三步:清理缓存、权限与残留配置
前面两步做完图标还是不出来,就要往缓存和权限上查了。
snap-store 的用户级缓存通常在~/snap/snap-store/目录下,如果内容损坏,会出现打开就闪退的情况。清理方式是把整个目录改名而不是直接删,方便出问题时回退:
mv ~/snap/snap-store ~/snap/snap-store.oldGNOME 软件那一侧的缓存则在~/.cache/gnome-software/,同样处理。改完名重新打开软件中心,它会重新生成一套干净的配置。
系统级的 snap 缓存也可以顺手清一次:
sudo rm -rf /var/cache/snapd/* sudo systemctl restart snapd权限方面,重点看/var/lib/snapd的所有者有没有被改动过。正常情况下它属于 root,如果之前有谁为了图方便chmod -R 777过,snapd 会拒绝启动或者行为异常:
ls -ld /var/lib/snapd属主应该是root root。不对的话改回来:
sudo chown -R root:root /var/lib/snapd注意:给系统目录批量改权限是排障里最容易"治病治出新病"的操作,改之前一定先记录原始权限,改完立刻验证服务状态。
5.4 如果还是不行:绕开软件中心直接命令行装
说实话,我个人的习惯是从来不指望图形化软件中心。它慢、搜索不准、有时候还推荐一堆不相干的 snap 应用。日常装软件,直接命令行效率高得多。
常见的几类需求,对应的命令其实就那么几条:
# 装具体应用 sudo snap install code --classic sudo apt install vlc # 搜索有哪些可选 snap find 关键词 apt search 关键词 # 看某个应用详情 snap info 包名 # 一次性装多个 sudo apt install git curl wget htop--classic这个参数值得说一下。snap 默认运行在沙箱里,权限收得很紧,像代码编辑器这种需要读取任意目录下的项目文件、调用外部命令的工具,必须用--classic模式安装,否则会出现"打开了但读不到项目文件"这类怪问题。看到某个 snap 应用行为异常,第一反应就该去查它是不是需要 classic 权限。
如果连命令行都装不上,那就得回到网络层面查了。先测 DNS 解析:
nslookup archive.ubuntu.com解析不出来就是 DNS 配置问题,检查/etc/resolv.conf;能解析但连不上,ping一下看丢包情况;如果是公司内网环境,还要确认有没有走内部软件源或者访问策略。
6. 装完之后的高频坑:输入法、字体、环境变量与解压乱码
软件装上了不等于能用。Ubuntu 20.04 上还有一批特别高频的"装完还有后续"的问题,几乎每个中文用户都会撞上一两次。
6.1 中文输入法从装到能用的完整流程
输入法这个问题,只装不配等于没装。20.04 默认是 ibus 框架,但你也可以换成生态更成熟的 fcitx。
以 fcitx 加拼音为例:
sudo apt install fcitx fcitx-googlepinyin fcitx-config-gtk im-config -n fcitxim-config -n fcitx这一步是设置默认输入法框架,很多人跳过这步,结果装完重启还是打不出中文。
然后注销重新登录(不是重启系统,注销当前会话就够了)。登录后还要补环境变量,否则在某些应用里输入法不生效。把这些写进~/.xprofile:
export GTK_IM_MODULE=fcitx export QT_IM_MODULE=fcitx export XMODIFIERS=@im=fcitx这里有个细节:如果你的会话用的是 Wayland 而不是 Xorg,.xprofile不一定被读取,这时候要么切回 Xorg 登录,要么把这几行写进~/.profile。判断自己在哪套显示协议下,用echo $XDG_SESSION_TYPE就行。
还有一个坑是安装顺序。想装第三方拼音输入法(比如从官网下的搜狗 deb 包),必须先装好 fcitx 框架,再装输入法包。反过来装,依赖会挂不上,表现出来就是安装过程报了一堆依赖错误,装完了输入法列表里也看不到。
6.2 环境变量改错导致命令找不到的复原方法
这是另一类高频事故。往/etc/profile或者~/.bashrc里改 PATH 的时候,把原来的内容覆盖掉了,或者写漏了一个冒号,重启之后所有基础命令都报command not found。
应急恢复有两条路。第一条是在当前会话里直接把 PATH 重置回去:
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin第二条更彻底,用一个不读取任何配置文件的干净 shell 启动:
bash --noprofile --norc进去之后用绝对路径打开出错的文件,把有问题的那行删掉或者注释掉:
/usr/bin/vi ~/.bashrc改 PATH 的正确姿势,永远是追加而不是覆盖:
export PATH=$PATH:/your/new/path写法上必须带$PATH,把原来的内容包含进来。再就是改/etc/profile之前先备份,这一类文件改坏了,普通用户连图形界面都可能登不进去。
6.3 zip 解压中文乱码与字体安装
Windows 上用压缩软件打出来的 zip,文件名多半是 GBK 编码,在 Ubuntu 上解压出来就是一串问号或者火星文。单次处理可以指定编码:
unzip -O cp936 压缩包.zip -d 目标目录/如果你的 unzip 版本不支持-O参数,换7z:
sudo apt install p7zip-full 7z x 压缩包.zip -o目标目录/已经解压出来、文件名已经乱掉的,可以用convmv批量转码,注意加--notest之前先用--notest的反面(也就是不加参数)跑一次预览:
sudo apt install convmv convmv -f gbk -t utf8 -r 目标目录/确认预览结果正常之后,再加--notest真正执行。
字体方面,系统级安装就是把字体文件放到/usr/share/fonts/下对应目录,用户级放到~/.local/share/fonts/,放完刷新缓存:
fc-cache -fv fc-list :lang=zh第二条命令用来确认中文字体有没有被正确识别。终端里中文显示成方块、代码注释里汉字变成方框,基本都是因为系统缺中文字体,装一个fonts-noto-cjk就能解决大部分场景:sudo apt install fonts-noto-cjk。
说到这里插一句个人体会:Ubuntu 20.04 这套软件安装和软件中心的坑,本质上都源于"图形化工具背后跑着一堆命令行组件"这个事实。搞清楚apt、dpkg、snap三条线各自的职责,把命令行当成主力工具,图形界面当成补充,你会发现 90% 所谓的"Linux 装软件难",其实只是没找对那个该敲的命令而已。