Making mirror://mirrors.ubuntu.com highly available
Solution 1:
Personally I think that the best way to select the best Ubuntu repositories mirrors is to use the GUI method:
Now, to improve the situation described in the question, you need to set some rules somehow. These rules must to act on mirrors.ubuntu.com
. I can suggest some rules as follow:
- make a list of best/preferred mirrors; there are a lot of mirrors as you can see here, here or here
- if you found a good mirror, add it to the list
- if a mirror was down or broken sometimes, it means that is not a good mirror and you should remove it from the list
- you can use
netselect
,apt-spy
orapt-fast
- and others, depending on your requirements.
Next, to see how you can work around, I can give you a method described step by step with three bash scripts examples. First script use the mirrors from the country you are in at the moment instead of mirrors.ubuntu.com/mirrors.txt
(for each country there is a text file with mirrors asociated; see http://mirrors.ubuntu.com/):
- In a terminal run
mkdir -p bin
- this command will make abin
directory in yourhome
folder if you don't already have it. - After run
gedit ~/bin/change_sources.sh
- this will create the new filechange_sources.sh
in gedit. - Copy and paste one of the next scripts in the new created file:
#!/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
or, something similar to what can be found at 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
or, a script using netselect
(download from here, install instructions here) as izx explained verry nice in this answer:
#!/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
- Save the file and close it.
- Go back into terminal and run:
chmod +x ~/bin/change_sources.sh
- to grant execute access for the script. - Just for test, to run your new script, type in terminal
~/bin/change_sources.sh
. It will give you an error, because you don't have the right to edit/etc/apt/sources.list
. So, usesudo ~/bin/change_sources.sh
- Edit the root user's crontab file using
sudo crontab -e
command and add the following line:
@hourly /home/$USER/bin/change_sources.sh
#change $USER with your user name
- I have set the cron job for every hour, but you can change as you wish or as you think is better. See http://en.wikipedia.org/wiki/Cron in this sense.
- Save the file and check the new crontab entry with
sudo crontab -l
.
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
From now, the file will be dynamically changed after it finds a change of the IP address.
It may not be the best solution, but, in my opinion, a good solution can be given in this way like in the scripts above.
Solution 2:
I appreciate all the input on this question, but since no one came up with a simple solution which fit our circumstances, I decided to fix the problem myself.
I created a tool (specifically for Ubuntu) which I call apt-spy2
.
The primary objective of this tool is to find a working mirror fast. Working is defined by that the mirror server is available and (hopefully :) up to date.
I make no assumptions about if the selected server is necessarily the closest and the fastest. I'm not doing any pings or GEO DNS tricks — but so far this works when something breaks.
How it works — in a nutshell:
- I use http://mirrors.ubuntu.com or launchpad's list of mirrors to retrieve servers.
- I do a simple check on each (for HTTP Response Status Code).
- LBNL, I update
/etc/apt/sources.list
.
Please note: This assumes that people play nice and put additional mirrors (e.g. 3rd party repositories into /etc/apt/sources.list.d
. But I guess that means there's room for improvement.
You can obtain this tool like so:
$ [sudo] gem install apt-spy2
The cli comes with list
, check
, fix
and help
(with extended information on how to use it).
I tried to document as much as possible in the project's README.
The current version is a very conservative 0.5.0
.
The code is open source and the license is liberal. And I take all contributions.
Solution 3:
There was this command at Debian 6.0.4 :
apt-spy
This did the job to find the next closest available server automatic and to generate a new sources.list
In Ubuntu this command seems not to exist ?
It still exists in Debian 7.0 wheezy :
https://launchpad.net/debian/wheezy/+source/apt-spy/+copyright
You can download your *.deb package here :
http://packages.debian.org/sid/apt-spy
... still searching for the sources ...
You obviously need Debian-7.0-Installation for to get the source-code after editing sources-list with entry :
deb-src http://http.debian.net/debian wheezy main
Then after sudo apt-get update you would simply suck the code with :
sudo apt-get source apt-spy