Created
April 3, 2021 06:20
-
-
Save loganlinn/51915851adef077316b3891d673c285f to your computer and use it in GitHub Desktop.
Example 16-43. Updating FC4 - Advanced Bash-Scripting Guide
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment