作为一名常年混迹在Linux环境下的开发者,我几乎每天都要在Ubuntu上装软件、卸软件。说实话,很多刚接触Ubuntu的人,第一反应是去应用商店点两下鼠标,但真正到了服务器(尤其是无桌面环境的云服务器),或者遇到商店里没有的软件包时,命令行就成了唯一也最高效的路径。
这篇内容不打算做成一本“命令字典”糊弄人,而是把我平时在实际项目中真正高频使用的安装软件命令,从原理到实操,从正常流程到踩坑恢复,完整梳理一遍。只要你能跟着走一遍,往后在Ubuntu上装东西基本不会发怵。
1. 装软件之前,先把安装方式选对
很多人一上来就问“安装命令是什么”,但Ubuntu装软件有好几条路,每条路的适用场景完全不一样。选错了路子,轻则装不上,重则把系统依赖搞得一团糟。我一般会把安装方式分成四类,按优先级排列。
1.1 在线仓库安装(apt)——最常见也最推荐
apt是Ubuntu和Debian系发行版的核心包管理器。它的工作机制是从软件源(也就是远程仓库)下载软件包,然后自动处理依赖关系,安装完以后还帮你做好升级和卸载的索引管理。用户体验上很像手机的应用商店,但比应用商店透明得多。
绝大多数常用软件,比如nginx、docker、python3-pip、git、vim,都能直接用apt安装。我自己的习惯是,能apt搞定的事情,绝不去折腾其他方式。原因很简单:依赖自动解析、版本受官方维护、卸载干净,对系统副作用最小。
1.2 本地deb包安装(dpkg)——用于下载的安装包
有时候软件官网不提供apt源,只给一个.deb文件下载链接,比如某些企业级工具、闭源软件,或者内网离线包。这时候就要用dpkg命令直接处理这个deb包。
但dpkg有个痛点:它不像apt那样自动拉取依赖。如果系统里恰好缺少某个动态库或依赖包,dpkg会直接报错,需要你手动把缺少的依赖补上。所以实际工作中更推荐用gdebi或者apt install ./xxx.deb这种带依赖解析的安装方式,而不是裸敲dpkg。
1.3 跨发行版通用安装(snap / flatpak)
snap是Ubuntu母公司Canonical力推的打包格式,特点是软件自带运行环境,和系统本身隔离开。好处是解决了依赖冲突,坏处是包体积大、启动稍慢。像VS Code、JetBrains系列、Spotify这些软件,用snap装其实很省事。
flatpak主要在非Ubuntu系里更流行,Ubuntu也能用,但我觉得如果没有特别的需求,普通用户直接用apt或snap就足够了,没必要再引入一层运行环境。
1.4 源码编译——最后手段
有些软件只发布源代码包,或者你需要自己调整编译参数(比如定制安装路径、优化指令集),这时候就得走源码编译的路子。编译安装的流程基本是configure->make->make install三步,后面我会用实例拆开细讲。
提示:源码编译执行比较繁琐,而且依赖重,确实没有预编译包可用时才建议尝试。日常用apt源解决不了的场景,通常先在snap源找找,都没有再考虑源码。
2. apt命令实操:从更新源到彻底卸载
apt是使用频率最高的命令族,但很多人只知道一个apt install,遇到源没更新、PPA冲突、锁定文件残留这些问题就不知道怎么处理了。这一节我把一套完整流程串起来讲。
2.1 装软件前的第一件事:update和upgrade到底先敲哪个
新手最容易犯的错误,就是拿到一台新机器,直接apt install xxx,结果提示Unable to locate package。原因多半是软件源的索引文件还没有拉取过,apt根本不知道去哪找这个包。
我建议的标准化顺序是:
sudo apt update这个命令的作用是重新同步软件源的软件包索引,不会改变系统里已安装的软件,只是刷新“目录”。刚拿到新系统、换了源文件(比如换了国内镜像源)、或者添加了新的PPA之后,务必先执行这一步。
至于upgrade,作用是把系统里所有可升级的软件统一升级到新版本。参照我的习惯,个人桌面环境可以隔一段时间跑一次,生产服务器则要谨慎,尽量在维护窗口期做,避免影响线上服务。
sudo apt upgrade把这两条命令分开记忆,很快就能理解包管理器的逻辑:update是“查新目录”,upgrade是“执行更新”。
2.2 搜索、查看和安装一个软件的全过程
假设我现在要装一个文本编辑器,但我不确定软件包的具体名字,命令行里给出的搜索方式是:
apt search editor结果会列出一大堆名称或描述中带editor的包。看重名信息时,还可以继续用apt show查看某个包的详细信息:
apt show vim这会显示出这个包的版本、依赖关系、维护者、描述等元数据。安装之前花30秒看一眼依赖关系,可以提前预判会不会影响系统里其他环境。
确认无误后正式安装:
sudo apt install vim -y-y参数表示遇到询问直接确认,适合脚本化操作,手动操作时也可以不加,敲一下回车的事。
如果软件源里有的包版本太老,而我需要新版,可以添加PPA。比如有个轻量编辑器,官方PPA里维护了更新的版本:
sudo add-apt-repository ppa:example/editor sudo apt update sudo apt install example-editor很多人踩坑是只执行了add-apt-repository,忘记再执行apt update,导致安装时提示找不到包。这三条命令是固定搭配,别拆开记。
2.3 卸载软件时如何做到“片叶不沾身”
卸载的干净程度直接影响系统的整洁度。先看最简单的一条:
sudo apt remove vim这条命令会卸载可执行文件,但会保留配置文件。如果你希望连配置文件一起清掉,用purge:
sudo apt purge vim如果是打算清理不再使用的依赖包(当时为了满足某个软件而自动装上的,现在软件卸了,依赖也空闲了),用:
sudo apt autoremove清理apt下载缓存里的deb包文件,释放磁盘空间:
sudo apt clean我通常在卸载大型开发工具链(比如卸载整个Node.js的apt版本、卸载旧版Docker)后,会把purge和autoremove连着执行一遍,把残留降到最低。这是很多教程里不提醒但实际使用频率很高的操作。
3. 处理本地deb包:dpkg的实战心得
服务器或者内网环境经常遇到没有外网的情况,需要手动下载deb包再安装。我拿一个例子演示:假设我已经下载了一个名为teamviewer_amd64.deb的文件。
3.1 最稳妥的deb包安装方式
虽然dpkg是底层工具,但我更推荐用apt去“按文件安装”,它能自动检测并安装该deb所需的依赖——这是裸用dpkg实现不了的:
sudo apt install ./teamviewer_amd64.deb注意路径前要加./,否则apt会以为你在尝试安装一个叫teamviewer_amd64.deb的包,去源里搜索,结果自然是找不到。
如果确实想用dpkg直接操作,安装命令:
sudo dpkg -i teamviewer_amd64.deb裸dpkg碰到依赖包缺失时会报dependency problems - leaving unconfigured。这种情况下不要强行重启或者反复安装,先运行下面这条命令修复:
sudo apt install -f-f参数会修复损坏的依赖关系,自动把缺失的依赖补上。经常有人问我“dpkg装一半卡住怎么办”,其实多半就是这一步没做。
3.2 查看deb包信息与文件列表
拿到一个不明来历的deb包,别急着装,先看看它是什么。
查看包的名称、版本、描述:
dpkg -I teamviewer_amd64.deb这里是大写的I,表示info。查看包会往系统里拷贝哪些文件路径:
dpkg -c teamviewer_amd64.deb安装之后,想确认某个文件属于哪个包,或者某个包是否已装:
dpkg -l | grep teamviewer dpkg -S /usr/bin/teamviewer第一条是列出所有已安装的、名称匹配teamviewer的包;第二条是查看某个具体文件来源。
3.3 卸载本地安装的deb包
卸载时不需要知道deb文件的路径,只需要包名。先用dpkg -l | grep 包名确认准确的包名,然后:
sudo dpkg -r teamviewer sudo dpkg -P teamviewer-r是remove,-P是purge,后者连配置文件一起删。实际工作中我用的比较多的是-P,尤其是反复安装测试同一个软件时,purge能确保上一个版本完全干净。
4. snap安装命令:适合不想折腾环境的懒人
snap包的设计思路简单粗暴:把软件和它依赖的运行环境打包在一起,装到系统里之后和系统其他部分隔离。这让它天生适合那些依赖老版本库、或者和系统环境有冲突的软件。
4.1 常用snap安装与更新操作
安装指定软件:
sudo snap install code --classic--classic参数表示允许软件访问系统资源时使用传统权限模型,像VS Code这一类需要读写用户目录、调用系统编译器的开发工具,基本都要加这个参数,否则运行起来会受限。很多刚接触snap的人在这里一头雾水,记一下就好:看到安装提示说明需要classic权限时,果断加上。
更新已装的snap软件:
sudo snap refresh code注意snap的更新命令是refresh,不是upgrade。它和apt体系用得不一样,别搞混了。
卸载:
sudo snap remove code查看本机已安装了哪些snap包:
snap list4.2 snap vs apt:我什么时候选哪个
我的经验其实很直接:如果这个软件apt源里有,而且版本够新,用apt;如果一个软件apt里版本老旧、或者官方推荐snap安装,那就用snap。比如docker,apt源里有可能版本滞后,而官方更推荐用仓库安装脚本;ffmpeg这类工具则apt够用。没有必要非此即彼,混着用才是常态。
snap还有一个坑,是它的运行目录占用双份磁盘空间(一份安装内容,一份运行缓存),小硬盘的服务器上装多了snap包会明显占空间。清理旧版本快照:
sudo snap set system refresh.retain=2这条命令加上之后,系统最多保留2个旧版本的快照,再新也不会积攒太多磁盘占用。如果你习惯长期使用snap,建议一开始就设置好这个参数。
5. 源码编译安装:把三步走吃透
最后讲源码编译。虽然在现代Ubuntu上,90%的场景用不到,但总有那么些软件只提供源码包,或者你需要做深度定制。了解这套流程也是理解Linux生态的重要一步。
5.1 configure、make、make install真实作用
我拿一个最典型的场景举例:某软件发布了最新的tar.gz源码包,解压后进入目录,你会看到configure脚本、Makefile.in模板、src目录等。
第一步,执行:
./configure --prefix=/usr/local/myappconfigure的作用是检查当前系统的编译环境、依赖库、内核头文件等,同时根据你在参数里指定的选项生成Makefile。--prefix指安装路径,默认情况下会装到/usr/local,但为了让项目文件聚在一起,方便打包迁移,我经常指定一个单独目录。
第二步:
make -j$(nproc)make按Makefile的规则调起编译器,把源代码变成二进制文件。-j$(nproc)是让make根据 CPU 核心数并行编译,我经常在编译大项目时用这个参数,速度提升非常明显。
第三步:
sudo make install把编译好的二进制、库文件、配置模板复制到系统目录。
5.2 源码编译常见的三个意外
编译失败是家常便饭,但仔细观察报错,大多出在三个地方。
第一,缺依赖头文件。比如编译要求有libssl,系统里却没有,报错通常会提示fatal error: openssl/ssl.h: No such file or directory。解决办法是安装对应的-dev包:
sudo apt install libssl-dev这类开发包命名规律很明显:库名加-dev后缀。缺哪个报错就装哪个对应的-dev包,这是源码编译最常用的排查思路。
第二,路径前没有权限。如果不加--prefix,软件默认装到/usr/local,make install时如果不用sudo,几乎一定会报注入权限错误。解决办法是在make install前加sudo,或者把安装路径改到用户目录下(--prefix=$HOME/.local)。
第三,升级系统后旧的编译缓存冲突。这时候在源码目录里清理一下再重新编译:
make clean make -j$(nproc)它会把之前生成的目标文件和临时文件清干净。别小看这个命令,我无数次在系统库升级后靠它救回编译环境。
6. 常见安装报错与排查速查表
搬了这么多年的砖,我把被问过最多、自己踩过最多的几个问题列成了一张速查表。每一个问题都对应着具体的报错关键词和处置动作,直接按图索骥就行。
| 现象 | 报错关键词 | 原因 | 处置方式 |
|---|---|---|---|
| 软件找不到 | Unable to locate package | 没有更新软件源索引 | 先执行sudo apt update,再重新install |
| 依赖报错卡住 | dependency problems | dpkg安装漏掉依赖 | 执行sudo apt install -f自动修复 |
| 无法获取锁 | Could not get lock /var/lib/dpkg/lock | 另一个安装进程未结束 | 不要乱删锁文件,先`ps aux |
| 添加PPA后装不上 | 404 Not Found | 源列表还没更新 | 执行sudo apt update,检查PPA是否支持当前系统版本 |
| deb包签名无效 | signature verification failed | 软件源公钥未导入 | 用sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 密钥ID导入(老旧方案,新版用signed-by更规范) |
| 编译缺头文件 | No such file or directory | 缺少-dev开发包 | 根据缺失库名安装libxxx-dev |
这些场景几乎覆盖了日常安装Ubuntu软件80%以上的问题。我特别想强调一下锁文件那条——有些人遇到Could not get lock,第一反应是rm /var/lib/dpkg/lock,这样做短期内能继续装,但极可能导致dpkg状态不一致,造成更多麻烦。先定位锁的持有进程才是正解。
7. 我平时会额外注意的几个习惯
最后分享几条安装软件时容易被忽略,但实际体验差别很大的习惯。
第一,替生产环境固定软件版本。我自己在做服务器环境部署的时候,很少直接apt install最新版,而是先apt-cache policy 包名查看可用版本,再用apt install 包名=版本号的方式固定装某个稳定版。生产环境求稳,不追逐最新,被最新版坑过的同行应该能懂这句话的分量。
第二,用apt list --installed审视一下系统里残留了多少再也没用过的软件包。每过一段时间清理一次,机器变干净的同时,依赖冲突概率也会明显下降。
第三,谨慎使用apt clean的优化场景。如果你的机器只是为了跑一个长期服务,并不需要缓存任何deb安装包,那定期清理没问题;但如果你经常在隔离网络里装同一套环境,建议把缓存留着,下次离线安装能省很多事。
命令本身并不复杂,复杂的是命令背后的包管理思路和依赖关系。把上面这些场景都亲手试一遍,Ubuntu安装软件这件事就算真正入门了。碰到没见过的报错,大胆去查错误日志和软件源文档,踩过的坑会让你记得更牢。