#!/bin/bash
#
# apt-sources-update
#
# by travisn000 <travisn000 at gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
myname=$(basename "$0");
export TEXTDOMAIN=apt-sources-update
export TEXTDOMAINDIR="/usr/share/locale"
# verbose output for debugging
setverbose () { set -xv; }
showhelp () {
echo -e $"
$myname is a utility that will download the latest PCLinuxOS apt
sources.list from the main ibiblio server, verify that they
have been recently synced to the ibiblio server, and test
all updated repositories for download speed.
Once testing is completed the user will be given a speed
rated list of repositories from which they can select a
default repository to use for future software needs.
It is meant to be run as a regular user, and will prompt
for root permisions before making any changes to the apt
sources.list file. This script also requires that zenity
is installed so that GUI dialogs are properly displayed.
Available console options to override default behavior include:.
-a, -age=<time in days> Allowed repo age before FAIL
-n, -number=<number of repos> Max number of official repos to keep (fastest)
-s, -sources=<url of file> Location of official online sources.list
-t, -timeout=<time in seconds> Time to start file download before FAIL
-v, -verbose Verbose output for debugging
-w, -write Prompt to write new sources.list to /etc/apt (root password)
-u, -usage Display sample command line usage, help
-h, -help Display this help message
"
[ -n "$1" ] && exit $1 # only exit if exit status is passed to function
}
usage () {
showhelp
echo -e $"
Examples:
$myname -timeout=3 -age=2
$myname -s http://myserver.org/sources.list
$myname -t 2 -a 2 -n 8 -w
"
exit
}
# Set script title
VERSION=0.3.1
TITLE=$"Repo Speed Test $VERSION"
WINDOW_ICON="/usr/share/pixmaps/synaptic.png"
TMP_DIR="$HOME/repo-speed-test"
TESTFILE="srclist.main.bz2"
REPO_BASE_YEAR="2010"
TESTFILEDIR="pclinuxos/${REPO_BASE_YEAR}/base/"
UPDATED_SOURCESLIST="http://distro.ibiblio.org/pclinuxos/repo${REPO_BASE_YEAR}/sources.list"
MEGA_GAMES_REPO="http://ftp.nl.freebsd.org/pub/os/Linux/distr/pclinuxos/megagames/apt/ pclinuxos/${REPO_BASE_YEAR} megagames"
TIMEOUT="3"
while getopts a:n:t:s:wvuh op
do case "$op" in
a) REPO_AGE=$(($OPTARG*1));;
n) REPOS_MAX=$(($OPTARG*1));;
t) TIMEOUT=$(($OPTARG*1));;
s) UPDATED_SOURCESLIST="$OPTARG";;
w) WRITE_APTSL=0;;
v) setverbose;;
u) usage;;
h|?) showhelp 0;;
esac
done
shift $(( $OPTIND-1 ))
[ -n "$1" ] && echo -e $"Extra parameter(s) \"$@\" ignored...\n"
if ! cd ~; then
echo $"Cannot change directory to your home directory... quitting."
exit 1
fi
for c in $(echo "/ | # ! = _ ~ :")
do if ! [[ "$@" =~ "$c" ]]; then
s=$c ; break
fi
done
if [ -z "$s" ]; then
echo $"Try again without using all of \"/|#!=_~:\" in your arguments... quitting."
exit 1
fi
# Check if kdialog exists, if not, use gdialog for some dialogs.
# Note: Most dialogs are pure zenity, but zenity does not have the yes/no function :(
if [ -f /usr/bin/kdialog ]; then
DIALOG=kdialog
else
DIALOG=gdialog
fi
if [ ! -e /usr/bin/zenity ]; then
$DIALOG --yesno $"Zenity is required to run this script.\n\nWould you like to install it now?"
if [ "$?" == "0" ]; then
ktsuss synaptic &
exit
elif [ "$?" == "1" ]; then
kdialog --sorry $"Exiting now"
exit
fi
fi
# check that package managers are closed
for idx in synaptic smart ksmarttray kpackage apt-get
do
if [ -n "`pidof $idx`" ]; then
zenity --window-icon="$WINDOW_ICON" --error --title="$TITLE" --text=$"Please close your package manager '$idx' and then click on the link again.\n\nExiting..."
# echo -e "Please close your ${idx} package manager and then try again.\n\nExiting...\n\n"
sleep 2
exit 1
fi
done
# Check if user is logged in as root ..or not ???
if [ "$UID" == "0" ]; then
zenity --window-icon="$WINDOW_ICON" --error --title="$TITLE" --text=$"Please <b>DO NOT</b> run this script as root!"
showhelp
echo -e $"\nPlease use this command as normal user, not root."
exit 1
fi
#############################################
## Execution starts here ##
#############################################
aptsl="/etc/apt/sources.list"
newaptsl="$TMP_DIR/sources.list.new"
atemp="$TMP_DIR/atemp.$$"
editsl_file () {
exec 9<${aptsl} #$aptsl
echo -e $"\n\nLocal repo line(s) found:\n"
while read -u 9 r
# do if [[ $r =~ $rpm_file ]]; then
do if [[ $r =~ $rpm_local ]]; then
echo -e "$r\n"
zenity --window-icon="$WINDOW_ICON" --question --text=$"The following local repository exists:\n$r\n\nWould you like to keep it?"
if [ "$?" = "0" ]; then
if ( echo $r | grep ^[[:space:]]*# ); then
echo -e "${r}\n">>$newaptsl
else
echo -e "# ${r}\n">>$newaptsl
fi
echo -e $"\n..successfully recovered; you may reactivate using Synaptic\n"
fi
fi
done
exec 9<&-
} ###### end editsl_file ######
editsl_pass () {
exec 9<${aptsl}
echo -e $"\n\nPASS repo line found:\n"
while read -u 9 r
do if [[ $r =~ $rpm_pass ]]; then
echo -e "$r\n"
zenity --window-icon="$WINDOW_ICON" --question --text=$"The following pass repository exists:\n$r\n\nWould you like to keep it?"
if [ "$?" = "0" ]; then
if ( echo $r | grep ^[[:space:]]*"#" ); then
echo -e "${r}\n">>$newaptsl
else
echo -e "# ${r}\n">>$newaptsl
fi
echo -e $"\n..successfully recovered; you may reactivate using Synaptic\n"
fi
fi
done
exec 9<&-
} ###### end editsl_pass ######
makesl () {
head=$"# Package repository URL's
# Signed repositories have a [<key>] where <key> is the name of the key
# as it appears in vendors.list. If you remove it, no digital signature check
# will be made.
"
kde_section="kde4"
#if [ -d /usr/share/kde4 ]; then kde_section="kde4" ; fi
#if [ `rpm -qa kdebase4|wc -l` -gt 0 ];then kde_section="kde4" ; fi
dsx="pclinuxos/${REPO_BASE_YEAR} main updates nonfree games ${kde_section}"
# echo -e "\nIf your network connection is not active, please"
# read -p "activate it now, then press Enter to continue. "
zenity --window-icon="$WINDOW_ICON" --info --title="$TITLE" --text=$"If your network connection is not active, please\nactivate it now, then press OK to continue. "
if [ "$?" != "0" ]; then
zenity --window-icon="$WINDOW_ICON" --error --title="$TITLE" --text=$"Operation Canceled! \n\nExiting $myname... "
exit 1
fi
echo -e $"\nRetrieving updated apt sources.list...\n"
rm -fR $TMP_DIR &>/dev/null
mkdir -p $TMP_DIR
wget --directory-prefix=$TMP_DIR $UPDATED_SOURCESLIST 2>&1 \
| sed -u 's/.*\ \([0-9]\+%\)\ \+\([0-9.]\+\ [KMB\/s]\+\)$/\1\n# Downloading \2/' \
| zenity --window-icon="$WINDOW_ICON" --progress --auto-close --title="$TITLE" --text=$"Downloading updated apt sources.list file..."
#| zenity --window-icon="$WINDOW_ICON" --progress --pulsate --auto-close --title="$TITLE" --text=$"Downloading updated apt sources.list file..."
if [ -f $TMP_DIR/sources.list ]; then
zenity --window-icon="$WINDOW_ICON" --info --title="$TITLE" --text=$"Connection successful.. \nRetrieved new sources.list file. "
# repo list with NO line breaks
# REPOSLIST=""
# for url in `grep rpm.*p:// $TMP_DIR/sources.list | sed -e 's@^[# \t]*rpm @@' | cut -d" " -f1`; do REPOSLIST="$REPOSLIST $url "; done;
# repo list with line breaks
REPOSLIST=( `grep rpm.*:/ $TMP_DIR/sources.list | sed -e 's@^[# \t]*rpm @@' | cut -d" " -f1` )
# echo ${REPOSLIST[@]}
else
zenity --window-icon="$WINDOW_ICON" --error --title="$TITLE" --text=$"Unable to retrieve new sources.list file. \n\n Verify internet connection and try again. "
exit 1
fi
ans=""
# while ! [[ $ans == [0-9] || $ans == [0-9][0-9] ]]; do
# read -p"Enter acceptable repo sync age (0-99 days): " ans
# done
[[ "$REPO_AGE" =~ ^[0-9]+$ ]] && ans=$REPO_AGE || ans=$(zenity --window-icon="$WINDOW_ICON" --scale --title="$TITLE" --text=$"Select acceptable repo sync age in days.. " --min-value=1 --max-value=10 --value=5 --step 1)
if [ "$?" != "0" ]; then
zenity --window-icon="$WINDOW_ICON" --error --title="$TITLE" --text=$"Operation Canceled! \n\nExiting $myname... "
exit 1
fi
DATE_OLD=$(date --date "now - $ans days" +%Y%m%d) #; echo $DATE_OLD
GOODLIST=""
BADLIST=""
REPOCOUNT=${#REPOSLIST[@]}
echo -e $"\nTesting repo sync age and download speeds..\n"
rm -f $TMP_DIR/repo_goodlist.txt
rm -f $TMP_DIR/repo_badlist.txt
cd $TMP_DIR
#for REPO in ${REPOSLIST[@]} ; do
for (( i=0; i<${REPOCOUNT}; i++ )); do
the_progress=$((100*${i}/${REPOCOUNT}))
URL="${REPOSLIST[$i]}${TESTFILEDIR}${TESTFILE}"
GETSPEED=$(curl --max-time ${TIMEOUT} --time-cond ${DATE_OLD} --silent --write-out %{speed_download} -O ${URL})
# GETTIME=$(curl --max-time ${TIMEOUT} --time-cond ${DATE_OLD} --silent --write-out %{total_time} -O ${URL})
GETSPEED=$( echo $GETSPEED| cut -d"." -f1 ) #make integer
# if [ "$GETTIME" == "0.000" ]; then
if [ "$GETSPEED" == "0" ]; then
echo $"# REPO: ${REPOSLIST[$i]}\nSTATUS: FAILED"
echo "${REPOSLIST[$i]}" >> $TMP_DIR/repo_badlist.txt
echo "$the_progress"
else
echo $"# REPO: ${REPOSLIST[$i]}\nSPEED: $GETSPEED bytes/second"
echo "$GETSPEED ${REPOSLIST[$i]}" >> $TMP_DIR/repo_goodlist.txt
echo "$the_progress"
fi
done | zenity --window-icon="$WINDOW_ICON" --progress --auto-close --title="$TITLE" --text=$"Starting repo speed test..." --width=400
# --pulsate
rm -f $TMP_DIR/$TESTFILE
REPO_SELECTION=$(sort -nr $TMP_DIR/repo_goodlist.txt |
awk -F" " '{print $2,"\n",$1}' |
zenity --window-icon="$WINDOW_ICON" --list --title="$TITLE" \
--column=$" Repo URL" --column $"bytes/second" \
--text=$"Select your preferred repo from the list below.\n\n(Ordered fastest to slowest - please do <b>NOT</b> use ibiblio.org)" --width=750 )
if [ "$REPO_SELECTION" == "" ]; then zenity --window-icon="$WINDOW_ICON" --error --title="$TITLE" --text=$"Operation Canceled! \n\nExiting $myname... "; exit; fi
finalrepolist=( `cat $TMP_DIR/repo_goodlist.txt | sort -nr | cut -d" " -f2` )
if [ -f $TMP_DIR/repo_badlist.txt ] ; then
echo
echo -e $"\nThe following mirrors timed out, are out of date, or are not valid :\n"
cat $TMP_DIR/repo_badlist.txt;
sleep 2
fi
echo -e $"\nPCLinuxOS official repositories: \n(ordered by speed-test results, fastest to slowest)"
echo -e $"(average download speed in bytes/seconds for ~500 KB file) \n\n"
sort -nr $TMP_DIR/repo_goodlist.txt | awk -F" " '{print $1," \t",$2}'
if [ "$finalrepolist" != "" ]; then
# find item in array
bash__is_in_array () {
haystack=( "$@" )
haystack_size=( "${#haystack[@]}" )
needle=${haystack[$((${haystack_size}-1))]}
for ((i=0;i<$(($haystack_size-1));i++)); do
h=${haystack[${i}]};
[ $h = $needle ] && return $i
done
}
bash__is_in_array "${finalrepolist[@]}" $REPO_SELECTION
n=$?
active_repo="${finalrepolist[$n]}"
echo -e $"\n\n Activating $active_repo"
echo -e $" Creating $aptsl\n"
[[ "$REPOS_MAX" =~ ^[0-9]+$ ]] && list_length=$REPOS_MAX || list_length=$(zenity --window-icon="$WINDOW_ICON" --scale --title="$TITLE" --text=$"Select number of online repositories to keep: " --min-value=1 --max-value=${#finalrepolist[@]} --value=5 --step 1)
if [ "$?" != "0" ]; then
zenity --window-icon="$WINDOW_ICON" --error --title="$TITLE" --text=$"Operation Canceled! \n\nExiting $myname... "
exit 1
fi
# write sources.list.new header
echo "$head" > $newaptsl
# add user selected online repo first (top of the repo list)
echo -e "rpm ${finalrepolist[$n]} $dsx\n" >> $newaptsl
# ask for enable megagames
zenity --window-icon="$WINDOW_ICON" --question --text=$"If you want to enable the repo for megames?" --title="$TITLE"
if [ "$?" = "0" ]; then
# add megagames repo next
echo -e "rpm ${MEGA_GAMES_REPO}\n" >> $newaptsl
else
echo -e "# rpm ${MEGA_GAMES_REPO}\n" >> $newaptsl
fi
rs="# rpm";
# write sources.list.new local / pass repositories
rpm_local="rpm.*file:/|rpm.*tp://localhost|rpm.*tp://192.168.|rpm.*tp://10.|rpm.*tp://172.16."
egrep -q "$rpm_local" ${aptsl} && editsl_file
rpm_pass="@"
# rpm_pass="rpm.*@"
egrep -q "$rpm_pass" ${aptsl} && editsl_pass
# write sources.list.new online repositories
for (( r=0; r<${list_length}; r++ )); do
if [ "$r" != "$n" ]; then # do not add user selected online repo.. it was already added above
echo -e "$rs ${finalrepolist[$r]} $dsx\n" >> $newaptsl
fi
done
else
echo -e $"\nUnable to contact any PCLinuxOS software repository \(REQUIRED\). \n\nExiting.. please verify your network connection and try again.\n\n"
zenity --window-icon="$WINDOW_ICON" --error --title="$TITLE" --text=$"\nUnable to contact any PCLinuxOS software repository \(REQUIRED\). \n\nExiting.. please verify your network connection and try again.\n"
sleep 3
exit 1
fi
} ###### end makesl ######
if ! [ -f "$aptsl" ]; then
echo -e $"Can\'t find ${aptsl} \n\nExiting... "
zenity --window-icon="$WINDOW_ICON" --error --title="$TITLE" --text=$"Can\'t find ${aptsl} \n\nExiting... "
exit 1
fi
root_script=backup-n-overwrite-sources.sh
makesl && cat > $TMP_DIR/$root_script <<EOF
#!/bin/bash
# REQUIRES ROOT PRIVLIGES
if [ \$UID -ne 0 ]; then
echo -e $"\nPlease use this script as root.\n"
exit 1
fi
if [ -f "$aptsl" ]; then
cp -f --backup $aptsl ${aptsl}.old #2>/dev/null
aptslbk=\$?
else
aptslbk=999
fi
[ "\$aptslbk" != "999" ] && force=1
[ -n "\$force" -a -f ${aptsl}.old ] && cp -f --backup=off $TMP_DIR/sources.list.new $aptsl 2>/dev/null
# -r => launch synaptic with repository selection dialog open
#( synaptic -r &>/dev/null )&
synaptic -r
echo -e \$(basename "\$0") complete..;
EOF
chmod 755 $TMP_DIR/$root_script
[[ "$WRITE_APTSL" == "0" ]] && zenity --window-icon="$WINDOW_ICON" --question --text=$"The repo speed test has completed and
a new apt sources.list has been saved to your home directory.
Would you like to overwrite your current sources.list file?
(a back up copy of the current file will be made)"
if [ "$?" = "0" ]; then
cd $TMP_DIR
mysu=`which gksu 2>/dev/null` || mysu=`which kdesu 2>/dev/null` && $mysu "./$root_script"
cd ~
zenity --window-icon="$WINDOW_ICON" --question --text=$"Would you like to remove the repo-speed-test working directory from your home folder?"
if [ "$?" = "0" ]; then
rm -fR $TMP_DIR &>/dev/null
fi
fi
[[ "$WRITE_APTSL" != "0" ]] && zenity --window-icon="$WINDOW_ICON" --warning --text=$"The repo speed test has completed and a new apt sources.list \nhas been saved to your home directory.\n\nTo activate it you must copy it to the /etc/apt directory."
echo $"${myname} is now finished."
echo; echo;
sleep 1