Guest User

pac-sync

a guest
Aug 13th, 2010
188
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.81 KB | None | 0 0
  1. #! /bin/bash
  2. #
  3. # bash script to check how up to date the pacman mirrors are
  4. #
  5. # This script reads the /etc/pacman.d/mirrorlist file to obtain a
  6. # list of mirrors; then queries only those mirrors from countries
  7. # of your choosing for their last update. If you want to ignore a
  8. # given mirror, then give it the old "double comment" in the
  9. # mirrorlist file, i.e.:
  10. #
  11. ##Server = ftp://mirrors.kernel.org/archlinux/$repo/os/$arch
  12. #Server = http://mirrors.kernel.org/archlinux/$repo/os/$arch
  13. #
  14. # in this case the ftp mirror would be ignored, while the http
  15. # mirror would be queried.
  16. #
  17. # It uses wget to read the "lastsync" file from each server then
  18. # writes this information to a file named /etc/pacman.d/mirrors.
  19. #
  20. # One of the these mirrors is then choosen as the preferred mirror
  21. # using a simple heurstic. The wget's are run in parallel and the
  22. # order in which they respond is noted. The most recently updated
  23. # mirror of the first 8 to respond (excluding those mirrors that
  24. # have not been updated since the last time you ran 'pacman -Sy')
  25. # will become the choosen mirror.
  26. #
  27. # This info will be written to the /etc/pacman.d/mirrors file.
  28. # My /etc/pacman.conf is set up to Include this file for core,
  29. # extra, and community.
  30. #
  31. # The choice of this mirror as the preferred one may not be the best
  32. # choice, but it is both responsive and has been recently updated.
  33. #
  34. ############## Edit this block to suit your taste ##############
  35. #
  36. # each country has to match listing in mirrorlist file (you may have
  37. # any number of countries, but DON'T separate the list with commas!)
  38. #
  39. countries=("Any" "United States" "Canada")
  40. #
  41. # suitable defaults
  42. #
  43. pd=/etc/pacman.d/
  44. infile=mirrorlist
  45. outfile=mirrors
  46. config=/etc/pacman.conf
  47. log=/var/log/pacman.log
  48. #
  49. ################################################################
  50. #
  51. get_sync_data() {
  52. sync_url=$(sed -e "s/\\\$repo.*/lastsync/" <<< $1)
  53. sync_time=$(wget -q -O - --tries=1 --timeout=10 $sync_url)
  54. if [[ "$?" == "0" ]]
  55. then
  56. [[ $sync_time =~ .*[^0-9] ]] && sync_time=$(date --date="$sync_time" +%s)
  57. let "delta = $2 - sync_time"
  58. let "d = delta / 86400"
  59. let "h = delta % 86400 / 3600"
  60. let "m = delta % 86400 % 3600 / 60"
  61. printf "#%3dd %2dh %2dm %s %d\n" $d $h $m $1 $delta
  62. fi
  63. }
  64. #
  65. # Acquire last sync data from mirrors
  66. #
  67. current_time=$(date +%s)
  68. echo -n "Querying mirrors ..."
  69. sync_data=$(
  70. for country in "${countries[@]}"
  71. do
  72. for url in $(sed -n -r "/# $country/,/^$/ s/^#?Server = // p" < $pd$infile)
  73. do (get_sync_data $url $current_time) & done
  74. done
  75. )
  76. echo
  77. script_name=$(sed "s!.*/\\(.*\\)!\\1!" <<< "$0")
  78. if [[ -z $sync_data ]]
  79. then
  80. echo "The network appears to be down as no mirrors could be contacted"
  81. echo "Retaining original $pd$outfile file."
  82. echo
  83. echo "$script_name aborted."
  84. echo
  85. exit
  86. fi
  87. #
  88. # Start building new 'mirrors' file ($pd$outfile)
  89. #
  90. [[ -e $pd$outfile ]] && mv $pd$outfile $pd$outfile~
  91. printf "# File auto-generated by '$script_name', do not edit.\n# $(date +%c)\n#\n" > $pd$outfile
  92. sed -r "s@((f|ht)tp://[^/]+).*\$@\\1/@" <<< "$sync_data" >> $pd$outfile
  93. echo "#" >> $pd$outfile
  94. #
  95. # Read pacman log file to determine date/time of last 'pacman -Sy'
  96. #
  97. b=[[:blank:]]
  98. logfile=$(sed -n "s/^LogFile$b*=$b*\\(.*\\)/\\1/p" $config)
  99. [[ -z $logfile ]] && logfile=$log
  100. diff_t=999999999
  101. dstr=$(grep "pacman *-S[^ ]*y" $logfile | tail -1 | sed -n "s/^\[\\(.*\\)\].*\$/\\1/ p")
  102. if [[ ! -z $dstr ]]
  103. then
  104. last_sync_time=$(date --date="$dstr" +%s)
  105. [[ "$?" -eq "0" ]] && let "diff_t = current_time - last_sync_time"
  106. fi
  107. #
  108. # Append preferred mirror to 'mirrors' file. Disgard any mirror that
  109. # has not been updated since last 'pacman -Sy'
  110. #
  111. awk "BEGIN{cnt=0}\$NF<$diff_t{if(cnt<8){cnt++; print;}}" <<< "$sync_data" |
  112. sort -s --key=2n --key=3n --key=4n |
  113. awk 'NR == 1 {print "Server =", $5}' >> $pd$outfile
  114. #
  115. # Check if any mirror has been updated recently enough
  116. #
  117. mirror_count=$(tail -1 $pd$outfile | sed -n '/^Server = / p' | wc --lines)
  118. if [[ "$mirror_count" -eq "0" ]]
  119. then
  120. [[ -e $pd$outfile~ ]] && mv $pd$outfile~ $pd$outfile
  121. cat $pd$outfile
  122. echo
  123. echo "No server has been updated since you last ran 'pacman -Sy'"
  124. echo "Retaining original $pd$outfile file."
  125. echo
  126. echo "$script_name aborted."
  127. echo
  128. exit
  129. fi
  130. #
  131. # Use preferred mirror and update
  132. #
  133. [[ -e $pd$outfile~ ]] && rm $pd$outfile~
  134. echo
  135. cat $pd$outfile
  136. echo
  137. echo "using log file: $logfile"
  138. tail $logfile
  139. echo
  140. echo "pacman -Syy"
  141. pacman -Syy
  142. echo
  143. #
  144. # declare two associative arrays
  145. #
  146. declare -A local_version
  147. declare -A sync_version
  148.  
  149. #
  150. # obtain list of packages needing upgrade along with current version number
  151. #
  152. pkg_count=0
  153. while read name version
  154. do
  155. [[ -z $version ]] && break
  156. local_version[$name]=$version
  157. let "pkg_count += 1"
  158. done <<< "$(pacman -Qu)"
  159.  
  160. echo -n "$pkg_count updated packages available."
  161. if [[ $pkg_count -gt "0" ]]
  162. then
  163. #
  164. # obtain new version numbers
  165. #
  166. echo " Run 'pacman -Su'."
  167. db_dir=$(pacman -v | sed -n 's/.*DB Path *: *\([^ ]*\).*/\1/p')
  168. for name in "${!local_version[@]}"
  169. do
  170. # x=(../foo*) expands x into an array containing the names
  171. # of each file currently matching '../foo*'
  172. sync_files=(${db_dir}sync/*/$name*/desc)
  173. for file in "${sync_files[@]}"
  174. do
  175. sname=''
  176. version=''
  177. lastline=''
  178. while read line
  179. do
  180. [[ "$lastline" =~ %NAME% ]] && sname=$line
  181. [[ "$lastline" =~ %VERSION% ]] && version=$line
  182. if [[ ! -z $sname && ! -z $version ]]
  183. then
  184. sync_version[$sname]=$version
  185. version=''
  186. sname=''
  187. fi
  188. lastline=$line
  189. done < $file
  190. done
  191. done
  192.  
  193. # output update information
  194. black='\e[0m'
  195. red='\e[0;31m'
  196. blue='\e[0;34m'
  197. green='\e[0;32m'
  198. for name in "${!local_version[@]}"
  199. do
  200. echo
  201. echo -ne " $name: $blue${local_version[$name]}"
  202. echo -ne " $black=> $red${sync_version[$name]}$black"
  203. done
  204. fi
  205. echo
  206. echo
  207. exit 0
Advertisement
Add Comment
Please, Sign In to add comment