#!/bin/bash # fc4upd.sh # Script author: Frank Wang. # Slight stylistic modifications by ABS Guide author. # Used in ABS Guide with permission. # Download Fedora Core 4 update from mirror site using rsync. # Should also work for newer Fedora Cores -- 5, 6, . . . # Only download latest package if multiple versions exist, #+ to save space. URL=rsync://distro.ibiblio.org/fedora-linux-core/updates/ # URL=rsync://ftp.kddilabs.jp/fedora/core/updates/ # URL=rsync://rsync.planetmirror.com/fedora-linux-core/updates/ DEST=${1:-/var/www/html/fedora/updates/} LOG=/tmp/repo-update-$(/bin/date +%Y-%m-%d).txt PID_FILE=/var/run/${0##*/}.pid E_RETURN=85 # Something unexpected happened. # General rsync options # -r: recursive download # -t: reserve time # -v: verbose OPTS="-rtv --delete-excluded --delete-after --partial" # rsync include pattern # Leading slash causes absolute path name match. INCLUDE=( "/4/i386/kde-i18n-Chinese*" # ^ ^ # Quoting is necessary to prevent globbing. ) # rsync exclude pattern # Temporarily comment out unwanted pkgs using "#" . . . EXCLUDE=( /1 /2 /3 /testing /4/SRPMS /4/ppc /4/x86_64 /4/i386/debug "/4/i386/kde-i18n-*" "/4/i386/openoffice.org-langpack-*" "/4/i386/*i586.rpm" "/4/i386/GFS-*" "/4/i386/cman-*" "/4/i386/dlm-*" "/4/i386/gnbd-*" "/4/i386/kernel-smp*" # "/4/i386/kernel-xen*" # "/4/i386/xen-*" ) init () { # Let pipe command return possible rsync error, e.g., stalled network. set -o pipefail # Newly introduced in Bash, version 3. TMP=${TMPDIR:-/tmp}/${0##*/}.$$ # Store refined download list. trap "{ rm -f $TMP 2>/dev/null }" EXIT # Clear temporary file on exit. } check_pid () { # Check if process exists. if [ -s "$PID_FILE" ]; then echo "PID file exists. Checking ..." PID=$(/bin/egrep -o "^[[:digit:]]+" $PID_FILE) if /bin/ps --pid $PID &>/dev/null; then echo "Process $PID found. ${0##*/} seems to be running!" /usr/bin/logger -t ${0##*/} \ "Process $PID found. ${0##*/} seems to be running!" exit $E_RETURN fi echo "Process $PID not found. Start new process . . ." fi } # Set overall file update range starting from root or $URL, #+ according to above patterns. set_range () { include= exclude= for p in "${INCLUDE[@]}"; do include="$include --include \"$p\"" done for p in "${EXCLUDE[@]}"; do exclude="$exclude --exclude \"$p\"" done } # Retrieve and refine rsync update list. get_list () { echo $$ > $PID_FILE || { echo "Can't write to pid file $PID_FILE" exit $E_RETURN } echo -n "Retrieving and refining update list . . ." # Retrieve list -- 'eval' is needed to run rsync as a single command. # $3 and $4 is the date and time of file creation. # $5 is the full package name. previous= pre_file= pre_date=0 eval /bin/nice /usr/bin/rsync \ -r $include $exclude $URL | \ egrep '^dr.x|^-r' | \ awk '{print $3, $4, $5}' | \ sort -k3 | \ { while read line; do # Get seconds since epoch, to filter out obsolete pkgs. cur_date=$(date -d "$(echo $line | awk '{print $1, $2}')" +%s) # echo $cur_date # Get file name. cur_file=$(echo $line | awk '{print $3}') # echo $cur_file # Get rpm pkg name from file name, if possible. if [[ $cur_file == *rpm ]]; then pkg_name=$(echo $cur_file | sed -r -e \ 's/(^([^_-]+[_-])+)[[:digit:]]+\..*[_-].*$/\1/') else pkg_name= fi # echo $pkg_name if [ -z "$pkg_name" ]; then # If not a rpm file, echo $cur_file >> $TMP #+ then append to download list. elif [ "$pkg_name" != "$previous" ]; then # A new pkg found. echo $pre_file >> $TMP # Output latest file. previous=$pkg_name # Save current. pre_date=$cur_date pre_file=$cur_file elif [ "$cur_date" -gt "$pre_date" ]; then # If same pkg, but newer, pre_date=$cur_date #+ then update latest pointer. pre_file=$cur_file fi done echo $pre_file >> $TMP # TMP contains ALL #+ of refined list now. # echo "subshell=$BASH_SUBSHELL" } # Bracket required here to let final "echo $pre_file >> $TMP" # Remained in the same subshell ( 1 ) with the entire loop. RET=$? # Get return code of the pipe command. [ "$RET" -ne 0 ] && { echo "List retrieving failed with code $RET" exit $E_RETURN } echo "done"; echo } # Real rsync download part. get_file () { echo "Downloading..." /bin/nice /usr/bin/rsync \ $OPTS \ --filter "merge,+/ $TMP" \ --exclude '*' \ $URL $DEST \ | /usr/bin/tee $LOG RET=$? # --filter merge,+/ is crucial for the intention. # + modifier means include and / means absolute path. # Then sorted list in $TMP will contain ascending dir name and #+ prevent the following --exclude '*' from "shortcutting the circuit." echo "Done" rm -f $PID_FILE 2>/dev/null return $RET } # ------- # Main init check_pid set_range get_list get_file RET=$? # ------- if [ "$RET" -eq 0 ]; then /usr/bin/logger -t ${0##*/} "Fedora update mirrored successfully." else /usr/bin/logger -t ${0##*/} \ "Fedora update mirrored with failure code: $RET" fi exit $RET