1. 问题
使用 Ubuntu 操作系统,执行
sudo apt-get update更新系统时,经常会见到类似如下所示的报错信息:
W: 无法下载 Hash 校验和不符
,系统更新失败。
这是一个烦人的问题,尤其是当以 Ubuntu 为基础构建容器镜像时,如果系统更新失败, Dockerfile 中的后续指令不会被执行。「校验和不符」( Hash Sum mismatch) 在 2012 年已经被确认是 Ubuntu 的一个 , 但是几年过去,还是没改好。出现这个错误的原因是 Ubuntu 下载的索引文件不是来自指定的软件源,而是网络服务提供商的缓存。网上给出的解决方案:sudo apt-get cleansudo rm -rf /var/lib/apt/listssudo apt-get update经实际验证,这种方法是无效的。
2. 解决方法
(1)代理
指定使用 HTTP 代理。如果是设置只对当前会话有效的临时代理,执行export http_proxy=http://yourproxyaddress:proxyportsudo apt-get updatesudo apt-get upgrade如果要设置持久代理,编辑
/etc/apt/apt.conf
,添加一行: Acquire::http::Proxy "http://yourproxyaddress:proxyport";,然后执行:
sudo apt-get updatesudo apt-get upgrade如果没有 HTTP 代理,只有 SOCKS 代理,首先安装
proxychains
程序,编辑 /etc/proxychains.conf
,指定 SOCKS 服务器的 IP 地址和端口;接下来,执行: sudo proxychains apt-get updatesudo apt-get upgrade(2)换协议网络服务商只使用了 HTTP 缓存,如果软件源还支持 HTTPS 或者 FTP 协议,修改
/etc/apt/sources.list
,把其中所有的 http://
换成 ftp://
,再执行系统更新。这种方法的不足是中国境内的软件源不支持 FTP 协议访问, Ubuntu 主服务器支持,但是网络速度会比较慢。(3)黑科技警告:这种方法是否有潜在问题,还有待持续一段时间的观察。不要在生产环境中使用。第一步:修改 apt
包的源代码,不让它报这个错。 sudo apt-get install build-essentialsudo apt-get build-dep aptsudo apt-get source apt此时,有一个
apt-1.0.1ubuntu2.7
的文件夹,包含 apt
包的源代码。修改 apt-pkg/accquire-item.cc
,查找 HashSumMismatch
关键词。第一个出现的地方是打印报错信息的函数,不用管。把剩下的五段代码都注释掉。例如, /*if (!ExpectedHash.empty() && !ExpectedHash.VerifyFile(DestFile)){RenameOnError(HashSumMismatch);Dequeue();return;}*/然后,在
apt-1.0.1ubuntu2.7
目录下,执行: makedpkg-buildpackage -us -uc -nc成功执行后,在
apt-1.0.1ubuntu2.7
的上一级目录中有新创建的一系列 .deb
文件。我们的修改,包含在 libapt-pkg4.12_1.0.1ubuntu2.7_amd64.deb
中。安装这个软件包,并标记为不更新: sudo dpkg -i libapt-pkg4.12_1.0.1ubuntu2.7_amd64.debsudo apt-mark hold libapt-pkg4.12第二步:把
/etc/apt/sources.list
中的软件源域名换成对应的 IP 地址。以中国服务器镜像为例,首先查找 cn.archive.ubuntu.com
对应的 IP 地址: dig cn.archive.ubuntu.com查询结果是:
cn.archive.ubuntu.com. 133 IN CNAME mirrors.aliyun.com.mirrors.aliyun.com. 133 IN A 112.124.140.210mirrors.aliyun.com. 133 IN A 115.28.122.210原来中国服务器就是阿里云镜像。编辑
/etc/apt/sources.list
, 把 cn.arhive.ubuntu.com
替换成 112.124.140.210
,保存。从此以后,就可以无烦恼更新系统了。