引言
日常 Jenkins job 运行,有段时间会遇到 apt 安装软件包 404
的情况,这种情况不是每次都发生的,但是会导致 Jenkins 失败,所以需要排查一下问题根源并解决。
关于 apt
apt(Advanced Package Tool)是 Linux 系统中用于管理软件包的一套工具。它允许用户安装、更新、升级和删除软件包。apt 是基于Debian 系统及其衍生系统(如 Ubuntu)中最常用的包管理工具。它简化了软件管理过程,通过自动处理依赖关系和软件包的安装,使得用户不必手动下载和安装每个软件包及其依赖。
apt 的主要功能包括:
- 安装新软件包:通过从软件仓库中下载和安装软件包,自动解决所需的依赖。
- 更新软件包列表:从设置的源(repositories)中更新可用软件包和它们版本的列表。
- 升级软件包:将系统上的软件包更新到最新版本,同时确保依赖关系得到满足。
- 删除软件包:从系统中删除不再需要的软件包,并清理它们的依赖。
- 清理未使用的软件包:删除那些已经不再被任何已安装软件包依赖的软件包。
apt 通过简单的命令行界面提供这些功能:
- sudo apt update:更新软件包列表。
- sudo apt upgrade:升级所有可升级的软件包。
- sudo apt install package_name:安装名为 package_name 的软件包。
- sudo apt remove package_name:删除名为 package_name 的软件包。
- sudo apt autoremove:自动删除不再需要的软件包。
apt 背后有一个庞大的软件仓库网络,为用户提供了广泛的软件选择和更新。
解决 apt 安装软件包 404 问题
问题
apt 安装 python3.8-venv 失败,404 Not Found,但是不是每次都失败的。
07:47:04 + sudo apt -y install python3.8-venv
07:47:04
07:47:04 WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
07:47:04
07:47:04 Reading package lists...
07:47:07 Building dependency tree...
07:47:07 Reading state information...
07:47:07 The following NEW packages will be installed:
07:47:07 python3.8-venv
07:47:07 0 upgraded, 1 newly installed, 0 to remove and 1 not upgraded.
07:47:07 Need to get 5452 B of archives.
07:47:07 After this operation, 27.6 kB of additional disk space will be used.
07:47:07 Ign:1 http://us-east-1.ec2.archive.ubuntu.com/ubuntu focal-updates/universe amd64 python3.8-venv amd64 3.8.10-0ubuntu1~20.04.9
07:47:08 Err:1 http://security.ubuntu.com/ubuntu focal-updates/universe amd64 python3.8-venv amd64 3.8.10-0ubuntu1~20.04.9
07:47:08 404 Not Found [IP: 54.87.19.168 80]
07:47:08 E: Failed to fetch http://security.ubuntu.com/ubuntu/pool/universe/p/python3.8/python3.8-venv_3.8.10-0ubuntu1~20.04.9_amd64.deb 404 Not Found [IP: 54.87.19.168 80]
07:47:08 E: Internal Error, ordering was unable to handle the media swap
07:47:08 Build step 'Execute shell' marked build as failure
分析
上面问题根源是 apt 安装 python3.8-venv 的版本是 python3.8-venv_3.8.10-0ubuntu1~20.04.9_amd64.deb 是老版本,而软件资源(repositories)中的是新版本 python3.8-venv_3.8.10-0ubuntu1~20.04.10_amd64.deb,所以找不到老版本,报 404 Not Found
http://security.ubuntu.com/ubuntu/pool/universe/p/python3.8/
sudo apt install 实际上会根据系统配置文件(通常是 /etc/apt/sources.list 文件及 /etc/apt/sources.list.d/ 目录下的文件)中列出的软件源(repositories)来搜索软件包。这些软件源可以包括多个不同的仓库,它们可能位于不同的服务器上,包括官方的 Ubuntu 仓库、第三方提供的仓库,以及本地的仓库等。
当你执行 sudo apt install package_name 命令时,apt 会:
查看本地的软件包索引列表,这个列表是通过 sudo apt update 命令更新的,它包含了所有配置的软件源中可用软件包的信息。
在这些软件源中搜索指定的软件包 package_name。
如果找到了软件包,它会检查依赖关系,确保所有需要的依赖包也都能被安装。
然后从相应的软件源下载软件包及其依赖,并在本地安装。
因此,sudo apt install 实际上是可以从配置的多个软件源中查找和安装软件包的,这取决于你的 sources.list 文件和 /etc/apt/sources.list.d/ 目录下的其他列表文件中的配置。
所以造成这个原因是,Jenkins 某些虚机本地的软件索引列表中,python3.8-venv 是老版本,所以 apt 会去安装这个老版本,而软件资源(repositories)这个版本已经不存在了,升级成新的版本了,但有些虚机本地的软件所以列表更新过,python3.8-venv 是新版本,所以安装导致有时成功,有时失败。
解决方案
如果本地软件包索引列表中的软件包是老版本的,那么当你使用 sudo apt install package_name 命令安装软件包时,apt 会根据这个本地索引去安装软件包,因此会安装老版本的软件包。
这是因为 apt 系统依赖于本地索引来确定可用软件包的版本。如果这个本地索引没有被定期更新(通过运行 sudo apt update),它可能不会反映软件源中最新的软件包状态。因此,即使软件源中有新版本的软件包,apt 也只能安装索引中列出的版本。
要确保安装最新版本的软件包,你应该定期运行 sudo apt update 来更新本地软件包索引,然后再安装或升级软件包。这样,apt 就能从软件源中获取最新版本的软件包信息,并进行安装。
所以在安装软件包时,先运行 sudo apt update 来更新本地软件包索引
sudo apt update
sudo apt -y install python3.8-venv