如果你正在折腾 Ubuntu 20.04 的服务器或者虚拟机,大概率会遇到两件不大不小的事:apt 更新速度一言难尽,以及运行某些服务命令时突然冒出No LSB modules are available.这样一句让人摸不着头脑的提示。这篇文章就把这两件事放在一起聊透:既要讲清楚 apt 源的修改逻辑、具体操作和常见坑,也要说明所谓“可选安装 No LSB modules”到底是什么意思、什么情况下才需要装。适合正在使用 Ubuntu 20.04、想优化软件包更新体验,或者被这行提示困扰的朋友,新手也能按照步骤完成。
1. 换源之前,先把这些问题想明白
1.1 为什么要改 apt 源,不改行不行
apt 是 Ubuntu 下最常用的软件包管理工具,所有软件包的下载地址都记录在源配置文件里。Ubuntu 默认使用的官方软件源,在很多实际网络环境下访问速度并不理想,尤其当你要安装大量依赖包时,长时间卡在下载阶段会让人非常难受。更现实的情况是,某些办公网络下官方源可能无法访问,apt update直接失败,这时候切换到一个可用的公共软件源,是成本最低的解决方案。
改源会不会影响安全性?不会。apt 在下载软件包时会校验数字签名,只要你不是随意添加来路不明的源,软件包本身的完整性验证依然有效。源地址只是告诉 apt“去哪里下载”,并不能决定软件包是否可信任。所以这里的关键不是“要不要换”,而是“换到哪个源、怎么保证源配置正确”。很多人一上来就照抄别人的 sources.list,结果版本代号写错,或者把 deb-src 全删了,反而搞出 404 和依赖问题。先理解源文件的结构,再做修改,比盲目复制省心得多。
1.2 源文件的结构该怎么看
在 Ubuntu 20.04 中,apt 的源配置分散在两个位置:传统的主配置文件/etc/apt/sources.list,以及目录/etc/apt/sources.list.d/下的若干.list文件。两者会被合并处理,并不存在其中一个禁用另一个的情况。主文件里的每一行都是一个源条目,格式大致是:deb <地址> <发行版代号> <组件列表>。地址指向软件仓库,代号告诉 apt 当前系统匹配哪个版本,组件则决定允许安装哪些类别的软件包。
Ubuntu 20.04 的固定代号是focal,所以你会看到focal、focal-security、focal-updates、focal-backports这样的名字。focal代表基础发布版本,focal-security是安全更新源,focal-updates是日常更新源,focal-backports是后续向后移植的软件源。组件名称里的main、restricted、universe、multiverse分别对应官方支持、受限支持、社区维护、非自由许可软件。理解了这些字段,任何一份 sources.list 你都能看懂,遇到问题也知道错在哪里。
2. Ubuntu 20.04 修改 apt 源实操
2.1 备份原文件,检查版本代号
动手改任何系统配置之前,备份是必须养成的习惯。很多人在改源后遇到问题想恢复,结果发现自己已经不记得原本写的是什么内容。一条简单命令即可备份:
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak.$(date +%F)备份文件名带上日期,比如sources.list.bak.2025-07-01,后续想恢复时一眼就能找到。如果系统里还有/etc/apt/sources.list.d/下面的自定义源,也可以一并打包备份。检查版本时,优先使用系统自带的lsb_release -a,它会输出当前发行版名称和代号。如果没有这个命令,读一下/etc/os-release也一样,grep VERSION_CODENAME /etc/os-release就能看到focal。
这里的逻辑很简单:源配置里的代号必须和系统版本保持一致。Ubuntu 20.04 对应focal,如果你写成了 18.04 的bionic,apt 会因为没有对应仓库而报错。所以我坚持先备份、再确认代号、最后动手编辑,顺序不要反过来。跳过备份直接操作,看起来更快,但一旦出问题,恢复成本远高于备份所花的那几秒钟。
2.2 三种修改方式怎么选
修改源的方式主要有三种。第一种是用 sed 直接在原文件里做文本替换,适合只把旧地址换成新地址的场景。比如把默认源地址整体替换成自己选择的地址,命令大概是这样:
sudo sed -i 's|http://.*archive.ubuntu.com/ubuntu|https://mirrors.example.com/ubuntu|g' /etc/apt/sources.list注意这里mirrors.example.com只是占位地址,实际使用时你要替换成自己选择的可用软件源地址。sed 替换有个问题:不同源地址的路径可能不一样,有的带/ubuntu,有的不带,有的还需要专门添加安全更新源。简单的全局替换很容易漏掉行,结果换了但又没完全换干净。
第二种是用文本编辑器把整个 sources.list 清空后重新写,我倾向于推荐这种方式。原因很简单,源文件总共也就几行内容,重写一次之后你对系统改了什么非常清楚,排查问题时心里有数。第三种是使用图形化的软件源管理工具,在桌面环境的系统设置里可以打开,它会列出多个可选站点,你只需要勾选,适合不喜欢碰命令行的朋友。但图形工具在纯服务器环境里不一定可用,所以本文后面还是以手动编辑为例。
2.3 一份可直接使用的 sources.list 结构
下面这份是我实际环境中比较常用的结构,地址部分用了占位地址mirrors.example.com,实际操作时请替换成你自己选择的可用源地址。不熟悉地址来源的话,可以先运行系统自带的软件源管理工具,从候选列表里选一个,再回头对比这份结构:
deb https://mirrors.example.com/ubuntu/ focal main restricted universe multiverse deb https://mirrors.example.com/ubuntu/ focal-security main restricted universe multiverse deb https://mirrors.example.com/ubuntu/ focal-updates main restricted universe multiverse deb https://mirrors.example.com/ubuntu/ focal-backports main restricted universe multiverse # deb-src https://mirrors.example.com/ubuntu/ focal main restricted universe multiverse写完保存退出,后续执行sudo apt update验证。第一行是基础源,负责 Ubuntu 主体软件包;第二行是安全更新源,它的重要性在 20.04 上丝毫没有降低;第三行是日常更新源,很多软件的小版本升级从这里来;第四行是 backports,不需要的话可以注释掉。注释掉的deb-src是源码包源,普通用户建议保留注释,省得每次apt update还要额外拉取源码索引。
2.4 更新索引与升级软件的区别
换完源后,最忌讳的是直接执行sudo apt upgrade。先分清概念:apt update只是从源下载软件列表并刷新本地索引,它不会改动任何已安装软件;apt upgrade才真正执行升级。刚换完源,本地可能还保留旧的索引缓存,直接 upgrade 相当于在不确定新源是否有问题的情况下贸然升级大批软件包,风险不划算。正确做法是先sudo apt update,观察是否成功;再看有多少软件可升级,apt list --upgradable可以列出来。
如果你这是刚装好的系统,下一步确实可以执行sudo apt upgrade或sudo apt dist-upgrade,把基础软件包补到最新。如果是生产环境或运行中的重要服务,建议只做apt update,把是否升级的决定权留给自己。另外,apt update的成功标准不是“没有输出”,而是最后没有红色错误信息。如果输出里出现 W 开头的警告,比如某些 GPG 签名失效,你仍然需要处理,否则这个源后续使用仍会带病运行。
2.5 换完之后如何确认源真的生效
改完源文件后,不要只看文件内容就以为成功了。一个简单有效的验证方式是执行apt-cache policy加某个软件包名称,例如:
apt-cache policy apt输出结果里会显示候选版本以及对应的源地址,如果源地址已经变成你刚写入的地址,说明当前生效的配置确实是新源。另一个方法是在apt update的输出中观察“命中”行,Hit表示索引更新成功,没有报错。如果不放心,还可以执行apt-config dump | grep -i sources查看当前合并后的源配置。
这里有一个容易被忽略的细节:/etc/apt/sources.list和/etc/apt/sources.list.d/下的文件会被合并生效。如果你在其中一个文件里写错了,但另一个文件里有正确配置,apt 可能仍然能工作,导致你误以为配置没问题。所以确认生效时,应该同时关注主配置文件和目录下的.list文件,不能只看某一个。
3. 关于 No LSB modules 到底要不要管
3.1 这句提示从哪里来
很多人在容器或精简版环境里执行service nginx status、service ssh status这类命令时,会看到一行service: No LSB modules are available.,然后就开始担心是不是系统坏了。其实这是service命令在尝试读取脚本的 LSB 头信息时给出的提示,它来自 sysvinit 脚本体系对 Linux 标准规范的支持。Ubuntu 20.04 已经转向 systemd,大部分服务不再依赖传统 init 脚本,但service命令为了兼容老脚本运行方式,仍然保留了对 LSB 信息的检测逻辑。
LSB 在这里并不是一个你需要完整安装的庞大软件包,它更多是一种约定。service命令会检查/etc/init.d/下脚本的开头是否包含### BEGIN INIT INFO这样的元信息块。如果脚本没有包含,或系统中缺少提供 LSB 辅助函数的组件,它就会提示No LSB modules are available.,然后继续按普通脚本方式执行。所以这个提示本质上是“缺少一种可选元数据”的说明,而不是“服务启动失败”的错误。
3.2 什么情况下才需要安装 lsb 模块
先说结论:对绝大多数普通用户,这个提示可以忽略。你的服务能启、能停、状态能看,就不需要为一句提示去装额外软件包。但有两个场景确实需要考虑安装。一个是你需要执行lsb_release -a或依赖lsb_release的脚本,却发现命令找不到,这时要装lsb-release。另一个是某些旧版/etc/init.d/脚本在运行时会调用/lib/lsb/init-functions,如果提示脚本执行异常,可以通过安装lsb-base来补充这部分函数库。
完整安装所谓的 lsb 模块,在 Ubuntu 20.04 上通常没有收益。它会把一大堆兼容层依赖拉进来,所占空间不小,但日常根本用不到。这也是标题里强调“可选”的原因。如果你在容器或极简环境中工作,追求的是小体积和低依赖,那就更不必装完整版本。优先保证系统已有软件正常工作即可。如果只是单纯被那句提示吓到,先确认服务能否操作,再决定要不要动环境,这才是理性的处理顺序。
3.3 安装与验证的具体操作
如果经过判断确实需要安装,操作非常简单。先刷新索引,然后安装对应包:
sudo apt update sudo apt install lsb-base lsb-release安装完成后,验证方式有两种。一是运行lsb_release -a,看能否正确输出发行版信息;二是重新执行之前出现提示的命令,比如service nginx status,观察提示是否消失。需要提醒的是,不同环境下提示消失的效果不完全一样。如果某个/etc/init.d/脚本本身就不带 LSB 信息块,安装lsb-base后service仍可能继续提示,这属于正常现象,因为问题出在脚本内容上,而不是系统缺包。
我自己的做法是:容器里保持最小安装,不装 lsb 相关包;普通虚拟机或物理机遇到脚本兼容性需要,再按需安装。判断依据很简单,如果你的软件运行一切正常,只是洁癖受不了那行提示,那就装lsb-base试试;如果提示伴随着服务操作失败,就要先检查脚本本身的语法和权限,而不是盲目加包。另外,安装前最好先看一眼当前系统里已经有哪些 lsb 相关包,使用dpkg -l | grep lsb查看,避免重复安装。
4. 换源后的常见问题排查
4.1 apt update 报错速查表
换源之后最常遇到的问题都集中在apt update阶段。与其一个一个问题描述,不如直接看速查表。
| 错误特征 | 可能原因 | 处理思路 |
|---|---|---|
| 无法解析域名或连接超时 | 源地址不可达或网络不通 | 换一个源地址,检查 DNS 配置 |
| 404 Not Found / 无法获取 Release 文件 | 版本代号与源不匹配,或源未收录该组件 | 核对 focal 代号,检查组件名 |
| 公钥错误 / NO_PUBKEY | 源缺少签名密钥 | 单独导入该源提供的公钥 |
| 哈希校验和不匹配 | 同步延迟或本地索引过期 | 执行 apt update,必要时 apt clean |
| 下载中断或文件过大 | 网络质量较差 | 重新 apt update,更换更近的源地址 |
表格只是提醒排查方向。细节上,最容易被忽略的是系统时间错误。之前我遇到过一台时钟跑偏的机器,apt update总是报公钥验证失败,因为签名对时间敏感。先检查date,时间不对就先校准。另外,apt clean清除的是下载缓存,不是源配置,很多人搞混这两个概念,导致清了缓存没解决任何问题。如果换了源地址后依然报错,把错误信息里出现的 URL 复制出来,手动用浏览器或下载工具访问一下,能立刻判断是源的问题还是网络的问题。
4.2 源文件被覆盖或格式错误怎么办
如果你在编辑器里保存文件时开了自动换行,或者用某些文本处理工具转换过文件,源文件可能混入回车符,apt 会读取失败。可以用cat -A /etc/apt/sources.list检查行尾是否有^M$这类异常符号。正常行尾应该是$,如果出现^M$,说明混入了 Windows 风格换行符,用编辑器重新保存或执行格式转换即可。手动编辑时,缩进不是问题,但每一行只能有一条源配置,末尾不能有多余空格,这些细节平时容易被忽略。
还有一个常见操作错误:在/etc/apt/sources.list.d/下新建了一个文件,但忘了给文件加.list后缀,apt 不会读取。反过来,如果这个目录下放了错误内容,它会和主文件里的配置合并,甚至因为重复条目造成奇怪的结果。排错时优先把可疑文件改名,比如加.disabled后缀,而不是直接删除,这样保留可回退的余地。修改完所有文件后,统一执行sudo apt update看效果。
4.3 版本代号写错了怎么办
这个问题值得单独说,因为很多人都是网上搜一段 sources.list,不看自己的系统版本直接粘贴。Ubuntu 20.04 的代号是focal,如果文件里写的是bionic或jammy,apt update大概率会返回对应库找不到文件的错误。排查方法很简单,运行grep VERSION_CODENAME /etc/os-release确认当前版本,然后把源文件里所有代号统一改对,再执行apt update。
另一种类似问题是混用多版本代号。比如主源写focal,安全更新源却写成了bionic。apt 不会直接报错,但会按错误源绑定错误的软件版本,长期运行可能引入不该有的依赖。我的建议是记住一条规则:所有行里的版本代号要保持一致,除非你有充分理由使用 backports 这类特殊源。改完之后用apt update观察错误是否消失,不要凭感觉判断。如果确认配置文件没问题但仍有 404,可以检查一下源地址路径末尾的斜杠是否遗漏,这也会导致拼接出的 URL 异常。
5. 几个容易忽略的细节与我的实操心得
5.1 软件源与安全更新源要分开
很多精简版教程图省事,只给你一行主源,忽略安全更新源。对一个长期运行的系统来说,focal-security这类安全源必须保留。安全补丁往往不会出现在普通升级通道里,如果把它注释掉,系统可能错过关键安全更新而不自知。有些人觉得第三方同步其实已经包含安全更新,但不同源的同步策略并不一样,不能把这个默认当作保证。
我平时的习惯是保留完整的四行源,也就是基础源、安全更新源、日常更新源、backports 源,然后把deb-src全部注释。backports 源虽然平时用不上,但保留它在需要某个较新软件版本时能快速切换,成本只是一行文字。当然,如果你对体积敏感或者希望最小化配置,把 backports 注释掉也没问题,但基础源和安全更新源这两条不要随便删。多花几秒钟把配置写完整,比日后为缺失的安全补丁担忧要值得多。
5.2 换完源之后包版本不一致怎么办
换完源后,本地包的索引会指向新源。由于新旧源的同步进度可能有差异,你可能会遇到部分软件显示可升级、但升级后又出现依赖冲突的情况。应对方式不是反复 upgrade,而是先用apt list --upgradable检查可升级列表,判断是否值得升级。如果某个软件被意外固定到了错误版本,可以用apt hold把它暂时钉住,等确认新源状态正常再取消固定。
还有一个容易被忽略的点:如果之前系统已经使用旧源很长时间,本地可能缓存了旧索引。换了新源后建议执行一次apt clean,把/var/cache/apt/archives下的旧包清掉,避免后续空间浪费。这个操作不会影响系统里已安装的软件,只是清理下载缓存,重要环境里反而更干净。我一般在换源后先clean,再update,然后再决定要不要upgrade,顺序固定下来之后出问题的概率小很多。
5.3 个人经验:LSB 模块选不选,看环境需求
写了这么多,最后说点实操层面的体会。对于No LSB modules are available这行提示,我没有建议每个人都去安装 lsb 相关包,因为这不是一个必须修复的系统错误。它更容易出现在容器、精简安装等环境里,这些环境本来就不追求传统 init 兼容,系统用 systemd 或直接调用脚本也能正常管理服务。强行安装大量兼容组件,反而违背了精简环境的设计意图。
反过来说,如果是在一台需要长期维护的虚拟机上运行自研脚本,或者有老运维习惯用/etc/init.d/检查服务状态,装一个lsb-base也就几秒钟的事,成本很低。我的经验是先看服务能否操作,再看工具链是否真的依赖lsb_release,两条都不满足就忽略提示。这样既节省时间,也不会因为强迫症去改变系统环境。希望这篇文章能帮你在 Ubuntu 20.04 上少走一点弯路。