#!/bin/bash # ex: set expandtab shiftwidth=4 softtabstop=4: # applyupdates.sh # v 0.5 # # Apply patches in ascending build order # (viewer updates are NOT installed by default) # # # version 7 and up only. . $HOME/etc/setenv.sh [ ! -d "$HOME/tmp" ] && mkdir $HOME/tmp function shorthelp() { echo echo "Usage: `basename $0` " echo " Available options" echo " =======================================================================" echo " -a Apply asroot updates up to ." echo " Must specify a version number" echo " (or 'all' to apply all asroot updates)" echo " -D Debug mode" echo " -d Download patches and install medleys" echo " -e Apply evals (make sure to patch to latest medley first" echo " -H Display detailed help" echo " -h Display help" echo " -v Apply viewer updates up to ." echo " Must specify a version number" echo " (or 'all' to apply all viewer updates)" echo " -p Apply plugin updates up to ." echo " Must specify a version number" echo " (or 'all' to apply all plugin updates)" echo " -n Download but don't install available patches" echo " -q Query installed server version" echo " -V Specify medsrv release (ex. 71b)" echo " -M Install/update the MG viewer" echo " -m Apply medleys up to version " echo " Must specify a version number" echo " (or 'all' to apply all medley updates)" echo " -y Anser 'yes' to all prompts" echo " -Q Query in shorter format" echo exit 0 } function longhelp() { echo echo " Example: '$0 -d -v 30 -p 15 -m 9' " echo " Will download all patches and apply viewers up to viewer 30," echo " plugins up to version 15, and medleys up to medley 9 (inclusive)" echo echo " Example: '$0 -d -v all -p all -m all' " echo " Will download all patches and apply all viewer, plugin, and medley patches" echo echo " Example: '$0 -n" echo " Will downlload all available patches." echo echo " Example: '$0 -v 40 -p all -m all' " echo " Will apply up to viewer 40, all plugin, and all medley patches" echo " (patches previously downloaded using '-n') " echo exit 0 } while getopts ":Ddv:hHnqV:eMyQp:m:a:" OPT ; do case $OPT in a) applyasroot="1" [ -z "$OPTARG" ] && shorthelp asroot_max="$OPTARG" ;; D) debug="1" ;; d) download="1" ;; h) shorthelp ;; H) longhelp ;; n) noinstall="1" # download only ;; q) queryversion="1" ;; v) applyviewer="1" [ -z "$OPTARG" ] && shorthelp viewer_max="$OPTARG" ;; p) applyplugin="1" [ -z "$OPTARG" ] && shorthelp plugin_max="$OPTARG" ;; V) [ -z "$OPTARG" ] && shorthelp medsrv_version="$OPTARG" ;; e) getevalpatches="1" ;; M) mg_viewer="1" ;; m) applymedley="1" [ -z "$OPTARG" ] && shorthelp medley_max="$OPTARG" ;; y) no_prompt="1" ;; Q) shortqueryversion="1" ;; *) echo "Unknown option or no option given" echo shorthelp ;; esac done # Get current installed version of medsrv if [ -z "$medsrv_version" ]; then if [ ! -f "$HOME"/etc/component.ls ]; then echo "$HOME/etc/component.ls dies not exist!" exit 1 fi medsrv_version=$(head -1 $HOME/etc/component.ls \ |awk '{ print $4 }' \ | cut -d - -f -1) fi # Strip any periods in the version if there are any version=$(echo $medsrv_version |sed 's/\.//g') patchdir="$HOME/patch" repository_dir="$patchdir/patch.$version" if [ ! -e "$repository_dir" ]; then echo "Repository directory not found." echo "Creating $repository_dir" mkdir -p $repository_dir echo fi medleydb="$patchdir/medley.db" viewerdb="$patchdir/viewer.db" plugindb="$patchdir/plugins.db" asrootdb="$patchdir/asroot.db" evaldb="$patchdir/eval.db" # The following patterns are for find medleypattern="patch.$version.medley-[0-9]+[0-9]?(.rc)?.tar.gz" pluginpattern="patch.$version.plugins[0-9]+[0-9]?(.rc)?.tar.gz" asrootpattern="patch.$version.asroot-[0-9]+[0-9]?(.rc)?.tar.gz" # evalpattern is defined later, after we know what medley is applied if grep "MG" $viewerdb > /dev/null 2>&1; then mg_viewer=1 fi if [ -n "$mg_viewer" ]; then viewerpattern="patch.$version.viewer[0-9]+[0-9]?MG(.rc)?.tar.gz" viewer_sortpattern="^patch\.[0-9]+[0-9]?\.[a-zA-Z]+([0-9]+[0-9]?)MG\.(rc\.)?tar.gz$" else viewerpattern="patch.$version.viewer[0-9]+[0-9]?(.rc)?.tar.gz" viewer_sortpattern="^patch\.[0-9]+[0-9]?\.[a-zA-Z]+([0-9]+[0-9]?)\.(rc\.)?tar.gz$" fi # The following patterns are for sorting medley_sortpattern="^patch\.[0-9]+[0-9]?\.[a-zA-Z-]+([0-9]+[0-9]?)\.(rc\.)?tar.gz$" plugin_sortpattern="^patch\.[0-9]+[0-9]?\.[a-zA-Z]+([0-9]+[0-9]?)\.(rc\.)?tar.gz$" asroot_sortpattern="^patch\.[0-9]+[0-9]?\.[a-zA-Z-]+([0-9]+[0-9]?)\.(rc\.)?tar.gz$" eval_sortpattern="^[0-9]+[0-9]?-m[0-9]+[0-9]?-eval-([0-9]+[0-9]?)\..*$" function getnumber() { local f=$1 # filename local re="${!2}" if [[ $f =~ $re ]]; then echo "${BASH_REMATCH[1]}" else echo "Error in getnumber" exit 1 fi return 0 } function mysort() { # $1 - a variable containing a list of filenames containing integers in the name # $2 - a variable containing a regular expression which, when matched against the # filename, will return an integer in BASH_REMATCH[1] # Output = the filenames in ascending order (based on the integer returned by the regex) # The function "sorts" by putting the filename in the i'th element of an array # where i is the integer in the filename. echo'ing the array outputs the elements in ascending order local inlist="${!1}" local re="${!2}" local sort_array local i for i in $inlist; do if [[ $i =~ $re ]]; then num=${BASH_REMATCH[1]} sort_array[$num]="$i" else echo "Error in mysort()" exit 1 fi done echo "${sort_array[@]}" } # Configure db files if they don't exist already, and get rid of redundant copies of patches # ${!variable} dereferences variable # (e.g. if a contains variableb, then ${!a} returns the contents of variableb as opposed to the name variableb) # Also, set the "newest_installed" and evalversion for t in medley viewer plugin asroot eval; do db="${t}db" sortpattern="${t}_sortpattern" if [ ! -f "${!db}" ]; then pattern="${t}pattern" installed="$(find $patchdir -regextype posix-extended -mindepth 1 -maxdepth 1 -regex "$patchdir/${!pattern}" |xargs --replace basename {})" sortedlist="$(mysort installed $sortpattern)" for f in $sortedlist; do echo "$f" >> ${!db} if [ "$t" == "eval" ]; then mv $patchdir/$f $repository_dir/ else rm $patchdir/$f fi done [ ! -f ${!db} ] && touch ${!db} fi if [ "$t" == "eval" ]; then export "newest_installed_${t}"="$(tail -n 1 ${!db}|grep $evalversion)" else export "newest_installed_${t}"="$(tail -n 1 ${!db})" fi if [ "$t" == "medley" ]; then if [ -n "$newest_installed_medley" ]; then evalversion="${version}-m$(echo $newest_installed_medley | awk -F "-" '{print $2}' | awk -F "." '{print $1}')" else evalversion="${version}-m0" fi evalpattern="$evalversion-eval-[0-9]+[0-9]?.*" fi done if [ -n "$queryversion" ]; then echo echo "Last installed medley patch is: $(echo $newest_installed_medley | sed -e 's/.tar.gz//g')" echo "Last installed plugin patch is: $(echo $newest_installed_plugin | sed -e 's/.tar.gz//g')" echo "Last installed asroot patch is: $(echo $newest_installed_asroot | sed -e 's/.tar.gz//g')" echo "Last installed viewer patch is: $(echo $newest_installed_viewer | sed -e 's/.tar.gz//g')" echo "Last installed eval patch is: $newest_installed_eval" echo echo "evalversion is: $evalversion" echo exit 0 fi if [ -n "$shortqueryversion" ]; then echo "serverVersion=$version" echo "serverPatch=$(echo $newest_installed_medley | sed -e 's/.tar.gz//g')" echo "asrootPatch=$(echo $newest_installed_asroot | sed -e 's/.tar.gz//g')" echo "viewerPatch=$(echo $newest_installed_viewer | sed -e 's/.tar.gz//g')" echo "pluginsPatch=$(echo $newest_installed_plugin | sed -e 's/.tar.gz//g')" exit 0 fi if [ -n "$mg_viewer" ]; then # viewerpattern will be the MG one if ! expr $newest_installed_viewer : $viewerpattern > /dev/null 2>&1; then newest_installed_viewer="patch.$version.viewer0MG.tar.gz" fi fi # If we got the d option, rsync the patch repository if [ -n "$download" -o -n "$noinstall" ]; then echo "Downloading updates from server.." echo "Please enter the patch server password at the prompt" rsync -va --progress -e ssh --exclude old_viewers root@support.erad.com:/home/medsrv/releases/patch.$version/ $repository_dir/ if [ $? -ne 0 ]; then echo "rsync returned with error $?" echo "aborting." exit 1 fi echo echo "Patch directory $repository_dir has been synchronized." echo if [ "$getevalpatches" == "1" -a -n "$evalversion" ]; then echo "Syncing eval patches applicable to $evalversion" rsync -va -e ssh root@helen.erad.com:/home/medsrv/releases/unreleasedpatches/evalpatches/$version/${evalversion}* \ $repository_dir/ --progress fi echo [ -n "$noinstall" ] && echo "Download only mode: exiting" && exit 0 fi # Build lists of patches to install # listnames are medley_to_install, viewer_to_install, etc. echo "Building lists of patches.." echo for t in medley viewer plugin asroot eval; do if [ "$t" == "viewer" -a -z "$applyviewer" ]; then echo "Skipping viewer updates (didn't get -v)" echo continue fi if [ "$t" == "plugin" -a -z "$applyplugin" ]; then echo "Skipping plugin updates (didn't get -p)" echo continue fi if [ "$t" == "medley" -a -z "$applymedley" ]; then echo "Skipping medley updates (didn't get -m)" echo continue fi if [ "$t" == "eval" ]; then if [ -z "$getevalpatches" ]; then echo "Skipping eval patches (didn't get -e)" echo continue elif [ -n "$medley_to_install" ]; then # medleys are evaluated before evals echo "Skipping evals because there are medley patches available." echo "Apply medleys and then re-run applyupdates to apply evals if desired" echo continue fi fi available="$HOME/tmp/${t}_available" [ -f "$available" ] && rm -f $available installlist="${t}_to_install" db="${t}db" pattern="${t}pattern" sortpattern="${t}_sortpattern" currentinstalled="newest_installed_${t}" avail_unsorted=$(find $repository_dir/ -regextype posix-extended -mindepth 1 -maxdepth 1 -regex "$repository_dir/${!pattern}" | \ xargs --replace basename {}) if [ -z "$avail_unsorted" ]; then continue fi avail_sorted="$(mysort avail_unsorted $sortpattern)" for f in $avail_sorted; do echo "$f" >> $available done if [ -n "${!currentinstalled}" ]; then currentinstalledver="$(getnumber ${!currentinstalled} $sortpattern)" else currentinstalledver="0" fi #if [ "$t" == "viewer" ]; then # # only install the newest viewer # toinstall="$(diff $available ${!db}| grep '<' | sed -e 's/< //g' | tail -n 1)" #else # toinstall="$(diff $available ${!db}| grep '<' | sed -e 's/< //g')" #fi toinstall="$(diff $available ${!db}| grep '<' | sed -e 's/< //g')" for f in $toinstall; do toinstallver="$(getnumber $f $sortpattern)" if [ "$t" == "medley" -a "all" != "$medley_max" ] && [ "$toinstallver" -gt "$medley_max" ]; then # User specified to only patch to medley "medley_max" break elif [ "$t" == "viewer" -a "all" != "$viewer_max" ] && [ "$toinstallver" -gt "$viewer_max" ]; then # User specified to only patch to viewer "viewer_max" break elif [ "$t" == "plugin" -a "all" != "$plugin_max" ] && [ "$toinstallver" -gt "$plugin_max" ]; then # User specified to only patch to plugin "plugin_max" break elif [ "$t" == "asroot" -a "all" != "$asroot_max" ] && [ "$toinstallver" -gt "$asroot_max" ]; then # User specified to only patch to plugin "plugin_max" break fi if [ "$currentinstalledver" -lt "$toinstallver" ]; then if [ -z "${!installlist}" ]; then export "$installlist"="$f" else export "$installlist"="${!installlist} $f" fi fi done if [ -n "${!installlist}" ]; then echo "$t to install:" for f in ${!installlist}; do echo "$f" installablepatches=1 done echo fi done if [ -n "$installablepatches" ]; then if [ -z "$no_prompt" ]; then echo "Hit a key to continue installation of the above patches or Control-C to abort." read a fi # Check for things that will make patch installation fail # Things like someone installing patches as root echo "Checking permissions and ownership.." non_medsrv_files=$(find $HOME/component ! -uid 530 -o ! -gid 530) if [ -n "$non_medsrv_files" ]; then echo;echo;echo echo "Found the following files in component not owned by medsrv." echo "these either need to be removed or ownership changed (as root) to medsrv.medsrv e.g.:" echo "chown medsrv.medsrv " echo echo "List of files:" echo "$non_medsrv_files" echo;echo;echo exit 1 fi chmod -R +w $HOME/component [ $? -ne 0 ] && { echo "ERROR! - Could not set all fies/directories writeable" ; exit 1 ; } for t in medley viewer plugin asroot eval; do installlist="${t}_to_install" db="${t}db" case $t in medley|viewer|plugin) for f in ${!installlist}; do echo "Applying $repository_dir/$f" tar -zxvf $repository_dir/$f -C $HOME/ > $HOME/tmp/untar_${f}.out 2>&1 [ $? -ne 0 ] && { echo "ERROR! - tar exited with an error" ; exit 1 ; } echo $f >> ${!db} readme="$HOME/README.$(echo $f | sed 's/.tar.gz//g')" mv $readme $patchdir/ done ;; asroot) for f in ${!installlist}; do echo "Installing asroot patch $repository_dir/$f" echo "Enter root password at the prompt" su - -c "tar -zxvf $repository_dir/$f -C /" > /dev/null if [ $? -ne 0 ]; then echo "Error installing asroot patch" echo "Aborting!" exit 1 else echo $f >> ${!db} fi done ;; eval) [ -z "${!installlist}" ] && continue while [ "$applyall" != "a" -a "$applyall" != "p" ]; do read -p "Apply [a]ll eval patches or [p]rompt for each one? (a/p):" applyall done for d in ${!installlist}; do eval_patch_name=$(find $repository_dir/$d -type f -name "*.tar.gz") if [ "$applyall" != "a" ]; then while [ "$confirmeval" != "y" -a "$confirmeval" != "n" ]; do read -p "Apply $eval_patch_name ? (y/n):" confirmeval done if [ "$confirmeval" != "y" ]; then echo "Not applying $eval_patch_name" unset confirmeval continue fi unset confirmeval fi echo "Backing up original files to $repository_dir/$d/$d.backup.tgz" unset backuplist for f in $(tar -tf $eval_patch_name); do [ -z "$backuplist" ] && backuplist="$HOME/$f" || backuplist="$backuplist $HOME/$f" done tar -czvf $repository_dir/$d/$d.backup.tgz $backuplist echo "Applying eval patch" tar -zxvf $eval_patch_name -C $HOME/ if [ $? -eq 0 ]; then echo "Successfully applied $eval_patch_name" echo $d >> ${!db} else echo "Failed applying $eval_patch_name" exit 1 fi done ;; esac done else echo echo "No new patches found to apply in $repository_dir" echo "Run $0 with the -d parameter to download any new patches." echo fi