#! /bin/sh # # ident data/SCCS/s.install_cluster_zone 1.3 02/02/06:14:24:52 SMI # # Script to install a patch cluster supplement for Solaris 10 or later # ######################################################################## set -e # # Force the path to first look in certain directories # PATH=/sbin:/usr/sbin:/bin:$PATH export PATH # # Supplement tag information # (Tag needs to be convertible to a valid filename too...) SUPPLEMENT_NAME="Solaris 10 x86 Recommended Patch Cluster" VALID_OS="5.10" PATCH_ORDER="patch_order" OS_REL=`uname -r` # Broadcast what we are doing # echo echo "Patch cluster install script for ${SUPPLEMENT_NAME}" echo logname=`echo ${SUPPLEMENT_NAME} | sed 's/ /_/g'`_log LOGFILE=/var/sadm/install_data/${logname} # # Command line and environment option processing # # (Default is *not* to save base objects) # Usage() { echo "usage: `basename $0` [-q] [-t] [-nosave] [target] [patchdir]" echo " [-q] - quiet option, suppresses interactive warning" echo " [-t] - Maintains the patchadd return codes from the" echo " Solaris release prior to Solaris 10" echo " [-nosave] - do not save original objects" echo " [target] - destination system to apply or query patches, can be one of:" echo " [-R client_root_path] - apply/query patch on bootable client root" echo " [patchdir] - optional pathname to directory of patches" } # # Validate the system and zones to ensure processing should continue # validate_system() { touch $LOGFILE || { echo "ERROR: $LOGFILE not writeable.\n" return 1 } if [ "$OS_REL" != "$VALID_OS" ]; then echo "ERROR: OS is not valid for this cluster. Exiting." return 1 fi ZONENAME="/sbin/zonename" if [ -x $ZONENAME ]; then if [ `$ZONENAME` != "global" ]; then echo "ERROR: install_cluster can only be applied to global zone. Exiting." return 1 fi else echo "ERROR: $ZONENAME cannot be found." echo " install_cluster for $SUPPLEMENT_NAME not applied. Exiting." return 1 fi } cleanup() { # # A little cleanup. # if [ "$finished" = "NO" ]; then failed_list="${failed_list} ${patch}" fi # # List the patches that were successfully installed (if any) # if [ " ${success_list}" != " " ] then echo echo "The following patches were able to be installed:" echo ${success_list} | /usr/bin/tr ' ' '\012' | sed 's/^/ /g' fi # # List the patches that failed installation (if any) # if [ " ${failed_list}" != " " ] then echo echo "ERROR: The following patches were not able to be installed:" echo ${failed_list} | /usr/bin/tr ' ' '\012' | sed 's/^/ /g' fi echo echo "For more installation messages refer to the installation logfile:" echo " ${LOGFILE}" echo echo "Use '/usr/bin/showrev -p' to verify installed patch-ids." echo "Refer to individual patch README files for more patch detail." echo "Rebooting the system is usually necessary after installation." } uid=`id | sed 's/uid=\([0-9]*\)(.*/\1/'` if [ "$uid" != "0" ] ; then echo "You must be root to execute this script." exit 1 fi ################################################################### # New functionality: user prompt driven by install_cluster_question ################################################################### # Check to see if the install_cluster_question file is present. # If it is, cat it to stdout - it includes the user prompt for # a passcode stored in the CLUSTER_README file. If it is present # but empty or unreadable (shouldn't happen, but it's possible), # err on the side of caution and provide a default prompt. answer_required="no" if [ -f install_cluster_question ] then answer_required="yes" if [ -r install_cluster_question -a -s install_cluster_question ] then cat install_cluster_question else echo "[empty/unreadable install_cluster_question file: default used]" echo " " echo "Special handling may be required for some of the patches in" echo "this cluster. Please refer to the CAUTION section in the" echo "cluster README for further instructions on how to proceed." echo " " echo "This section also contains a passcode that will need to be" echo "provided below to allow the install_cluster script to continue" echo "running." echo " " echo "Please enter passcode:" fi fi # If the question file is present, look up the passcode in the # CLUSTER_README file. Try to anticipate various ways in which # PASSCODE: may appear in the README file. # Look for PASSCODE:, remove any tab characters, look for PASSCODE: # optionally preceded by blanks, only use the first matching line, # strip away PASSCODE: and any blanks before or after it. if [ "$answer_required" = "yes" ] then answer_string=`grep PASSCODE: CLUSTER_README | tr -d '\011' | egrep -e "^ *PASSCODE:" | head -1 | sed -e "s/^ *PASSCODE: *//"` # If the answer string cannot be found, improvise. Provide a # diagnostic message, set the answer to a known value, and # provide it to the user so that cluster installation may # proceed. if [ -z "$answer_string" ] then echo " " echo "[ERROR: 'PASSCODE:' missing/malformed in CLUSTER_README]" echo " " echo "The passcode value expected in the CLUSTER_README file" echo "cannot be determined. Please type 'proceed' (no quotes)" echo "to proceed with cluster installation:" answer_string="proceed" fi # Prompt user for the answer string. If it's wrong, exit. read user_response if [ ! "$user_response" = "$answer_string" ] then echo "Passcode is incorrect; exiting." exit 1 fi fi # end of passcode retrieval/response/check block ################################################################### # end of install_cluster_question / passcode processing ################################################################### finished="NO" saveold='' useOldOSErr='' quiet="NO" target="" while [ "$1" != "" ]; do case $1 in -nosave) saveold='-d';; --nosave) saveold='-d';; -n) saveold='-d';; -q) quiet='YES';; -t) useOldOSErr='-t';; -R) shift if [ $# -gt 0 ] && [ ! -d $1 ]; then echo "$1 client root path not found?" exit 1 else target="-R $1" fi;; -*) Usage; exit 2;; *) if [ "$finished" = "YES" ]; then Usage; exit 2 fi # # Where do we find the list of patches to install # (we need an absolute pathname...) # # This is done to maintain the cwd to PATCHDIR to # suppress auto unmounts... if [ ! -d $1 ]; then echo "$1 optional patch directory not found?" exit 1 else cd $1 finished="YES" fi ;; esac shift done PATCHDIR=`pwd` if [ "$quiet" != "YES" ]; then cat << EOF *WARNING* SYSTEMS WITH LIMITED DISK SPACE SHOULD *NOT* INSTALL PATCHES: With or without using the save option, the patch installation process will still require some amount of disk space for installation and administrative tasks in the /, /usr, /var, or /opt partitions where patches are typically installed. The exact amount of space will depend on the machine's architecture, software packages already installed, and the difference in the patched objects size. To be safe, it is not recommended that a patch cluster be installed on a system with less than 4 MBytes of available space in each of these partitions. Running out of disk space during installation may result in only partially loaded patches. Check and be sure adequate disk space is available before continuing. EOF while . do echo "Are you ready to continue with install? [y/n]: \c" read reply case $reply in y) break;; n) exit;; *) echo invalid response, enter only 'y' for yes or 'n' for no;; esac done fi # # The patch reference directory must exist # if [ ! -d /var/sadm/patch ]; then mkdir /var/sadm/patch chown bin /var/sadm/patch chgrp bin /var/sadm/patch chmod 555 /var/sadm/patch fi # # If using save feature: # Approximate and set cluster save size value. The maximum save space # needed should be about no more than half of the actual patch cluster size # since the patch installation procedure will use compression to save files, and # patches with multiple architecture packages will only have appropriate # packages installed on the system. # if [ "${saveold}" != -d ]; then echo "Determining if sufficient save space exists..." BASESIZE=`du -sk $PATCHDIR | cut -f1` SUPPLEMENT_SIZE=`expr $BASESIZE / 2` bytes_avail=`df -b /var/sadm/patch | tail -1` bytes_avail=`echo $bytes_avail | sed 's/.*\ //'` if [ ${SUPPLEMENT_SIZE} -gt ${bytes_avail} ]; then echo "Insufficient space in /var/sadm/patch to save old files." echo "Space required in kilobytes: ${SUPPLEMENT_SIZE}" echo "Space available in kilobytes: ${bytes_avail}" exit 1 else echo "Sufficient save space exists, continuing..." fi else echo "The nosave option was used. Objects will not be saved." fi # # First validate system. # validate_system || exit 1 # # Install all the patches in patch_order file in PATCHDIR # echo "Installing patches located in $PATCH_ORDER file in ${PATCHDIR}" echo "" >> ${LOGFILE} echo "" >> ${LOGFILE} echo "*** Install ${SUPPLEMENT_NAME} begins `date` ***" >> ${LOGFILE} echo "*** PATCHDIR = ${PATCHDIR} ***" >> ${LOGFILE} echo "" >> ${LOGFILE} set +e finished="YES" success_list="" failed_list= result=0 trap 'echo; echo Interrupted ... Please wait; cleanup; exit 1' 1 2 3 15 # Check for existence of patch_order file if [ -f $PATCH_ORDER ]; then echo "Using $PATCHDIR/$PATCH_ORDER file for patch installation sequence" for patch in `cat $PATCH_ORDER` ; do if [ -d $patch ]; then echo "Installing ${patch}..." | tee -a ${LOGFILE} finished="NO" ( /usr/sbin/patchadd ${saveold} ${useOldOSErr} \ ${target} ${patch} ) >> ${LOGFILE} 2>&1 result=$? if [ ${result} -ne 0 ]; then echo " Installation of ${patch} failed. Return code ${result}." failed_list="${failed_list} ${patch}" else echo " Installation of ${patch} succeeded. Return code ${result}." success_list="${success_list} ${patch}" fi finished="YES" fi done else echo "" echo "ERROR: $PATCH_ORDER file does not exist. Unable to install cluster." fi cleanup if [ " ${failed_list}" = " " ]; then exit 0 else exit 1 fi