使mirror://mirrors.ubuntu.com具备高可用性

我们是一个分布式团队,这就是为什么我们的虚拟机使用Ubuntu mirror://设置。我们的/etc/apt/sources.list文件如下:

deb mirror://mirrors.ubuntu.com/mirrors.txt lucid main restricted universe multiverse
deb mirror://mirrors.ubuntu.com/mirrors.txt lucid-updates main restricted universe multiverse
deb mirror://mirrors.ubuntu.com/mirrors.txt lucid-backports main restricted universe multiverse
deb mirror://mirrors.ubuntu.com/mirrors.txt lucid-security main restricted universe multiverse

这本身就很惊人,对于在不同地点工作的人来说非常有帮助——减少了本地定制等等的必要性。理论上应该有故障转移。
但是在日常使用中,这个设置经常出现故障。我想说这个星期已经出现了2-3次。
现在,mirrors.ubuntu.com返回的是ftp.uni-bayreuth.de作为我最近的镜像站点。不幸的是,它似乎已经宕机了。
这个情况已经持续了几个小时,镜像站点由大学的志愿者托管,而今天是星期五,我对能够很快解决这个问题的希望不高。
只是说说而已,我的问题是:
  • 有人在使用这个吗?
  • 你是如何处理停机时间的?(我的临时解决方案是一个shell脚本)
  • 我如何帮助改善这种情况?

@RaduRădeanu - 这是我第一次听说netselect... 8oþ - dschinn1001
@RaduRădeanu 有趣的建议!干杯!我正在尝试使用您的帖子中更新最多的mirror:方法。我的问题是,当最快的镜像失败时,就没有故障转移,我就卡住了。 - Till
创建自己的Ubuntu镜像是一个选择吗? - Mitch
@Till 你能告诉我你是否可以拥有自己的镜子吗? - Mitch
您可能会喜欢阅读这条评论 - Braiam
6个回答

个人认为选择最佳的Ubuntu软件源镜像的最好方法是使用图形界面(GUI)的方式:

download server

现在,为了改善问题中描述的情况,你需要以某种方式设定一些规则。这些规则必须对mirrors.ubuntu.com起作用。我可以提出一些建议的规则如下:
- 制作一个最佳/首选镜像列表;你可以在这里hereherehere找到很多镜像。 - 如果你找到一个好的镜像,将其添加到列表中。 - 如果一个镜像有时候无法访问或损坏,那说明它不是一个好的镜像,你应该将其从列表中移除。 - 你可以使用netselectapt-spyapt-fast等工具。 - 还有其他工具,根据你的需求而定。
接下来,为了让你知道如何解决问题,我可以给你提供一种逐步描述的方法,并附上三个bash脚本示例。第一个脚本使用当前所在国家的镜像,而不是使用mirrors.ubuntu.com/mirrors.txt(每个国家都有一个与之关联的文本文件,请参考http://mirrors.ubuntu.com/):
  • 在终端中运行mkdir -p bin - 这个命令会在你的home文件夹中创建一个bin目录,如果你还没有的话。
  • 然后运行gedit ~/bin/change_sources.sh - 这将在gedit中创建一个名为change_sources.sh的新文件。
  • 将下面的其中一个脚本复制粘贴到新创建的文件中:
#!/bin/bash

export DISPLAY=:0

if ! [ "`ping -c 1 google.com`" ]; then
    notify-send "No internet connection"
    exit 0  
fi

ip=$(curl -s 'http://ipecho.net/plain')
country=$(curl -s 'http://geoiplookup.net/geoapi.php?output=countrycode' \
    | awk '{ print toupper($2) }')
release=$(lsb_release -sc)

file="/etc/apt/sources.list"
old_file="/etc/apt/sources.list.old"

line=$(head -n 1 $file)
new_line="## Ubuntu Repos for $ip"

if [ "$line" == "$new_line" ] ; then
    exit 0
fi

cp -f $file $old_file

printf "$new_line
deb mirror://mirrors.ubuntu.com/$country.txt $release main restricted universe multiverse
deb mirror://mirrors.ubuntu.com/$country.txt $release-updates main restricted universe multiverse
deb mirror://mirrors.ubuntu.com/$country.txt $release-backports main restricted universe multiverse
deb mirror://mirrors.ubuntu.com/$country.txt $release-security main restricted universe multiverse
" > $file

notify-send "$file has been changed" "The old file has been put in $old_file"

exit 0

或者,类似于可以在http://repogen.simplylinux.ch/找到的东西:
#!/bin/bash

export DISPLAY=:0

if ! [ "`ping -c 1 google.com`" ]; then
    notify-send "No internet connection"
    exit 0  
fi

ip=$(curl -s 'http://ipecho.net/plain')
country=$(curl -s 'http://geoiplookup.net/geoapi.php?output=countrycode' \
    | awk '{ print tolower($2) }')
release=$(lsb_release -sc)

file="/etc/apt/sources.list"
old_file="/etc/apt/sources.list.old"

line=$(head -n 1 $file)
new_line="## Ubuntu Main Repos for $ip"

if [ "$line" == "$new_line" ] ; then
    exit 0
fi

cp -f $file $old_file

printf "$new_line
deb http://$country.archive.ubuntu.com/ubuntu/ $release main restricted universe  multiverse
deb-src http://$country.archive.ubuntu.com/ubuntu/ $release main restricted universe multiverse

## Ubuntu Update Repos for $ip
deb http://$country.archive.ubuntu.com/ubuntu/ $release-security main restricted universe multiverse
deb http://$country.archive.ubuntu.com/ubuntu/ $release-updates main restricted universe multiverse
deb-src http://$country.archive.ubuntu.com/ubuntu/ $release-security main restricted universe multiverse
deb-src http://$country.archive.ubuntu.com/ubuntu/ $release-updates main restricted universe multiverse
" > $file

notify-send "$file has been changed" "The old file has been put in $old_file"

exit 0

或者,使用netselect脚本(从这里下载,安装说明在这里)如izx这个答案中非常好地解释了。
#!/bin/bash

export DISPLAY=:0

if ! [ "`ping -c 1 google.com`" ]; then
    notify-send "No internet connection"
    exit 0  
fi

url=$(netselect \
    `wget -q -O- https://launchpad.net/ubuntu/+archivemirrors \
        | grep -P -B8 "statusUP|statusSIX" \
        | grep -o -P "(f|ht)tp.*\"" \
        | tr '"\n' '  '` \
    | awk '{print $2}')
release=$(lsb_release -sc)

if [ "$url" == "" ] ; then
    exit 0
fi

file="/etc/apt/sources.list"
old_file="/etc/apt/sources.list.old"

cp -f $file $old_file

printf "## Ubuntu Best Repos
deb http://extras.ubuntu.com/ubuntu $release main
deb-src http://extras.ubuntu.com/ubuntu $release main
deb $url $release main universe restricted multiverse
deb http://security.ubuntu.com/ubuntu/ $release-security restricted universe main multiverse
deb $url $release-updates restricted universe main multiverse
" > $file

notify-send "$file has been changed" "The old file has been put in $old_file"

exit 0

保存文件并关闭。
返回终端并运行以下命令:chmod +x ~/bin/change_sources.sh - 为脚本授予执行权限。
只是为了测试,要运行您的新脚本,请在终端中键入~/bin/change_sources.sh。它会给出错误,因为您没有编辑/etc/apt/sources.list的权限。所以,请使用sudo ~/bin/change_sources.sh 使用sudo crontab -e命令编辑root用户的crontab文件,并添加以下行:
@hourly /home/$USER/bin/change_sources.sh  
#change $USER with your user name

我已经设置了每小时的cron job,但你可以根据自己的意愿或者认为更好的方式进行更改。在这方面,请参考http://en.wikipedia.org/wiki/Cron
保存文件并使用sudo crontab -l命令检查新的crontab条目。

NOTE: To revert the changes made by this script, delete the cron job and follow the indications from the picture above or use next command in terminal:

cp -f /etc/apt/sources.list.bak /etc/apt/sources.list
从现在开始,文件在发现IP地址变化后将会动态改变。
这可能不是最好的解决方案,但在我看来,可以通过上述脚本的方式提供一个好的解决方案。

感谢您周到的回复。有几件事情需要说明。我们拥有的这些虚拟机没有图形界面,所以传统的点和点击方法不可用。正如我之前提到的,我已经有一个脚本来修复我的镜像源。如果必要的话,我知道如何解决这个问题。但我的目标是改善整体的“mirrors:”情况。 - Till
2我猜,如果在Linux上的GUI能被认为是传统方式的话,我会进行争论。:) 但无论如何:你的第一个脚本解决了我没有的问题。镜像语法已经获取到我的德国镜像,或者美国或其他地方的人们。第二个脚本使用国家镜像——它们似乎可用带宽最少(在launchpad的archivemirrors列表中看到过)。第三个脚本假设速度最快(或者最近的)镜像确实是最好的。回到起点。我现在正在编写一个小的apt-spy脚本。稍后在这里更新。 - Till
最后但并非最不重要的一点是,只是为了确保:我非常清楚有脚本化的方法来解决mirrors.ubuntu.com出现故障或返回“broken”服务器的问题。但我希望修复这个部分,而不是维护脚本或镜像列表。 - Till
1@Till Well, 你的问题是“如何应对停机时间?”和“我如何帮助改善这种情况?”。我展示了我是如何应对的,并建议了你如何帮助改善...另外,如果你读到我的回答末尾,你会看到我意识到“这可能不是最好的解决方案,但我认为可以通过类似上面的脚本来提供一个好的解决方案”。最后,如果你有兴趣修复/改善损坏的服务器,这个话题在这里是离题的,你应该与那些服务器的所有者交谈。 - Radu Rădeanu
2我不认为这是离题的。各种Canonical/Ubuntu的人告诉我把我的问题添加到这里。这也是我来这里的原因,我想也是为什么有一个悬赏分配的原因。 - Till
1@Till 是的,这个问题很好,但不像你在这些评论中重新表述的那样。除非是相应服务器的管理员,否则没有人会在这里回答“如何修复一个损坏的镜像服务器”。 - Radu Rădeanu
1我不想修理那台服务器,我想修复选择算法和缺乏故障转移的问题。 - Till
@Till 所以你需要以某种方式设置一些规则。这些规则必须作用于 mirrors.ubuntu.com/mirrors.txt。我们回到了这个评论 - Radu Rădeanu
由于geoiplookup.net在上述脚本中不再起作用,因为它现在会返回一个完整的HTML页面,所以你必须使用geoiplookup XML API并解析XML(或找到其他服务)。 - ChrisWue

我感谢大家对这个问题的所有意见,但由于没有人提出一个适合我们情况的简单解决方案,所以我决定自己解决这个问题。
我创建了一个专门为Ubuntu设计的工具,我称之为apt-spy2。
该工具的主要目标是快速找到一个可用的镜像。可用指的是镜像服务器可用,并且(希望是)最新的。
我不假设选择的服务器一定是最近的和最快的。我不会进行任何ping测试或地理DNS技巧,但目前在出现故障时这种方法有效。
它的工作原理很简单:
1. 我使用http://mirrors.ubuntu.com 或者 launchpad's list of mirrors 来获取服务器列表。 2. 我对每个服务器进行简单的检查(检查HTTP响应状态码)。 3. 最后,我更新/etc/apt/sources.list文件。
请注意:这假设人们友好地玩耍并将其他镜像(例如第三方存储库)放入 `/etc/apt/sources.list.d`。但我想这意味着还有改进的空间。
您可以通过以下方式获取此工具:
``` $ [sudo] gem install apt-spy2 ```
该命令行界面带有 `list`、`check`、`fix` 和 `help`(包含有关如何使用它的扩展信息)。
我尽可能在项目的 README 中进行了文档记录。
当前版本非常保守,为 `0.5.0`。
该代码是开源的,许可证宽松。我接受所有的贡献。

你把这个上传到Ubuntu软件仓库了吗? - Braiam
@Braiam 你可以通过以下方式获取这个工具:sudo gem install apt-spy2 - Radu Rădeanu
@RaduRădeanu 我在问他是否已经上传了,因为我对将某些东西打包到Debian中很感兴趣。 - Braiam
@Braiam 我没有打包它,但如果有人愿意打包的话,我会欢迎的。 :) - Till
@Braiam 顺便说一句,这在Debian上可能行不通。 ;( 只适用于Ubuntu。 - Till

在Debian 6.0.4中有这个命令:
apt-spy
这个命令可以自动找到最近可用的服务器并生成新的sources.list。
在Ubuntu中似乎不存在这个命令?
在Debian 7.0 wheezy中仍然存在。

https://launchpad.net/debian/wheezy/+source/apt-spy/+copyright

您可以在此处下载您的*.deb软件包:

http://packages.debian.org/sid/apt-spy

...还在寻找来源...

显然,您需要进行Debian-7.0-安装以获取源代码并在编辑源列表时添加以下条目:

deb-src http://http.debian.net/debian wheezy main

然后,在使用sudo apt-get update命令更新之后,您只需使用以下命令提取代码:

sudo apt-get source apt-spy


谢谢你的建议,apt-spy看起来确实很不错。我不确定那样行得通。每次我在Ubuntu上安装Debian的东西时,由于其他依赖关系,它迟早会出问题。 - Till
@Till - 每次Linux要求更高的时候,总是需要做更多的探索。 - dschinn1001
1在Ubuntu上构建它:https://rubygems.org/gems/apt-spy2 和 https://github.com/lagged/apt-spy2 - Till
@嗨,你的意思是:建造它…!还是已经建好了…?- 我下次会注意的 - 现在这里正好是月圆之夜,我有点迷糊... - dschinn1001
你真快! - dschinn1001
直到你可以寄到我个人资料中的地址,没问题的,我会把终端输出通过邮件发给你...现在我需要休息一下,明天见。晚安。 - dschinn1001
运行gem update apt-spy2应该能解决所有问题。我还没有查看邮件。我休了几天假,但刚刚发现了一个错误。 :) - Till

也许不是使用你喜欢的解决方案,但为.deb文件设置一个本地缓存应该是理想的,当你下载几兆字节的软件包时(其中大部分我敢打赌都是相同的),由于你从同一台服务器下载,你可能愿意牺牲一台电脑来建立缓存,以减轻服务器的负担。
步骤
你应该能够在一台硬盘空间较大的机器上设置apt-cacher(你会需要它)。你可以使用Apt-cacher服务器指南进行配置,但我们先快速回顾一下。
  1. 安装 apt-cacher

    sudo apt-get install apt-cacher apache2

  2. 编辑 /etc/default/apt-cacher 并将 autostart 的值设置为 1,这样当机器启动时缓存会自动启动。
  3. 重新启动 apache sudo /etc/init.d/apache2 restart
  4. 使用 http://ip-of.your.cache:3142/apt-cacher 测试您的缓存。
  5. 您应该允许主机使用缓存,因此请编辑 /etc/apt-cacher/apt-cacher.conf 并查找 allowed_hosts 这一行。您可以设置子网如 192.168.0.0/24 或者使用 * 表示所有主机。
  6. 寻找一个快速可靠的服务器。您可以使用 apt-spy 来完成(此命令可能需要几个小时,因为它还会测试每个服务器的速度)。
  7. 在您的客户端上有两个选项:

    • sources.list 设置如下:

    deb http://ip-of.your.cache:3142/the.server.you.like/ubuntu/ lucid main restricted universe multiverse

    ip-of.your.cache 替换为您的缓存的 IP 地址,将 the.server.you.like 替换为您将要使用的服务器的主机名。您可以使用多行。

    • 或者设置 apt 使用代理:编辑 /etc/apt/apt.conf.d/01proxy 并添加以下行:

    Acquire::http::Proxy "http://ip-of.your.cache:3142";


如果您在全球范围内使用apt-spy,它将持续一段时间...但是您可以通过以下命令与边界接近(例如欧洲):apt-spy -d testing -a Europe - dschinn1001
@dschinn1001 -d testing 闻起来像Debian。 - Braiam
好的,然后:apt-spy -a Europe - dschinn1001
"downvote"? - 我没有点踩啊?- 有时候我不小心用鼠标点击了一下 - 我从来不是有意地点踩!所以我给你点赞了!谢谢。 - dschinn1001

你可以尝试搭建自己的Ubuntu镜像。这样更新将会是本地的。

apt-mirror需要高速互联网连接和大量的磁盘空间

使用apt-mirror来搭建自己的Ubuntu镜像非常简单。

1) 进入apt-mirror库。备份你的sources.list文件,操作如下:

sudo cp /etc/apt/sources.list /etc/apt/sources.list.old

2) 将sources.list文件进行编辑,如下所示:
gksudo gedit /etc/apt/sources.list

3)然后在新的一行插入以下内容:
deb http://apt-mirror.sourceforge.net/ apt-mirror

4) 让我们更新软件包索引
sudo apt-get update

5) 并安装apt-mirror
sudo apt-get install apt-mirror

6) Apt-mirror现在已经设置好了,让我们告诉它要镜像哪些服务器。
sudo cp /etc/apt/mirror.list /etc/apt/mirror.list.old
gksudo gedit /etc/apt/mirror.list

默认配置会将您下载的文件放在/var/spool/apt-mirror文件夹中。下面是mirror.list文件的样子:
############# config ##################
#
set base_path /media/silo/repo
#
# if you change the base path you must create the directories below with write privlages
#
# set mirror_path $base_path/mirror
# set skel_path $base_path/skel
# set var_path $base_path/var
# set cleanscript $var_path/clean.sh
# set defaultarch <running host architecture>
set nthreads 20
set tilde 0
#
############# end config ##############
deb http://archive.ubuntu.com/ubuntu lucid main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu lucid -updates main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu lucid -backports main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu lucid -security main restricted universe multiverse
clean http://archive.ubuntu.com/ubuntu

这只是镜像二进制包,但如果你想要源代码包,你应该插入适当的行。它们通常采用以下形式:
deb-src http://gh.archive.ubuntu.com/ubuntu/ lucid main restricted

7) 现在运行apt-mirror。这可能需要一段时间。如果你无法一次性下载所有文件,不要担心,apt-mirror可以恢复下载(按下Ctrl+C组合键终止它,然后在想要继续时重新运行它)。好了,像这样运行apt-mirror:
sudo apt-mirror /etc/apt/mirror.list

还可以查看如何使用apt-mirror创建本地Debian/Ubuntu镜像

来源:使用Apt-mirror创建自己的Ubuntu镜像


如果我没记错的话,apt-mirror 在 Ubuntu 软件源中是可用的。 - Braiam
顺便提一下,确保注意到需要大量硬盘空间来下载完整的镜像 ;) - Braiam
谢谢你的回答,这是一个很好的资源来设置镜像,我已经考虑过了,但是我需要在至少三个不同的地方进行设置。我知道我在这里有点挑剔,但我仍然觉得mirrors.ubuntu.com应该可以工作。 :) - Till
@till mirrors.ubuntu.com将永远无法解析mirrors.ubuntu.com,但会返回距离您最近的服务器。问题在于它所解析的服务器不可靠。您最好选择官方列表中可靠的服务器。 - Braiam
@Braiam 你有什么想法,为什么它会返回不可靠的镜像? - Till
由于您的物理位置,您可以手动选择可靠的镜像,而不是依赖自动镜像。这些镜像旨在为经常旅行的人(使用便携式电脑,也称为笔记本电脑)提供服务,而不是用于静态位置的系统。 - Braiam

我写了一个名为apt-select的Python脚本,作为GUI方法的CLI替代品。
该脚本通过TCP查询每个镜像,将具有最低延迟的镜像打印到stdout,并生成一个新的sources.list文件。还有多个选项可供选择,可以从排名镜像列表中进行选择,并获取镜像的最后更新时间和带宽容量等信息。