#!/sbin/sh ########################################################################## # bootsys # # @(#) bootsys: $Revision: 10.44 $ # # Tool to reboot a running system from the Ignite-UX server from which # this script is run. # export PATH=/opt/ignite/bin:/usr/bin:/usr/sbin:/sbin unset LANG # Need consistant output from commands usage="\ bootsys [-a|-w] [-dvhr] [-i \"configuration\"] [-s grace] client1 [client2 ...] Reboot the listed clients from the Ignite-UX server. Options: -a => Install client in automatic mode. -w => Have client wait for the Ignite-UX server to control it. -d => Don't exit if remsh to a client fails - proceed with others. Also prevents prompting for a password to enable remsh access. -h => Don't insert client host information into RAMFS - rely on DHCP. -r => Don't reboot client - just prepare it to be rebooted. -f => Force removal of any prior client configuration from server. -s grace => use shutdown instead of \"reboot -q\" with specified grace period. -v => Verbose. -i \"cfg\" => Use the given INDEX cfg for all clients listed. client => hostname of system to reboot under Ignite-UX. client:IP => system to boot, but specifying an alternate IP address to use. " warning_timeout_value=5 # change to 1 to prevent any auto_mode=false wait_mode=false d_opt=false h_opt=false r_opt=false f_opt=false verbose=false cfg="" shutdown_grace="" to_be_removed="" tmp_cfg_file=/tmp/bts.$$ tmp_output=/tmp/out.$$ blk_tmp=/tmp/btsys.blk.$$ this_user="$(id -un)" # used to setup remsh access. typeset -i num_clients=0 typeset -i cn=0 typeset -i errs=0 bootsys_prep="/opt/ignite/lbin/bootsys_prep" boot_lif="/opt/ignite/boot/boot_lif" INSTALL="/opt/ignite/boot/INSTALL" INSTALLFS="/opt/ignite/boot/INSTALLFS" VINSTALL="/opt/ignite/boot/VINSTALL" VINSTALLFS="/opt/ignite/boot/VINSTALLFS" LOGFILE=/var/opt/ignite/logs/bootsys set -u # aid in catching script errors set +o noclobber # ensure >file works exit_val=1 # Open up an alternate way of writing to stderr which is needed # for the interrupt_sig handler to work while in hang_guard subprocess # or else its output is put to $tmp_output exec 3>&2 do_cleanup() { rm -f $to_be_removed rm -f $tmp_output rm -f $blk_tmp if [ -w $LOGFILE ] ; then echo "bootsys exit: (pid: $$) $(date) (exit status: $exit_val)" >> $LOGFILE fi exit $exit_val } trap do_cleanup EXIT interrupt_sig() { if [ -w $LOGFILE ] ; then echo "ERROR: bootsys terminated by (user) signal." >> $LOGFILE fi echo "ERROR: bootsys terminated by (user) signal." >&3 exit_val=1 do_cleanup } trap interrupt_sig SIGABRT SIGINT SIGQUIT SIGTERM ########################################################################## # Print the first IP address that nslookup returns for the given host. # get_ip_addr() { nslookup $1 2>/dev/null /dev/null | awk 'BEGIN { FS="[, \t]+"} /Name:/ {print $2}') if [ "$full_name" = "" ] ; then echo $1 else echo $full_name fi } ########################################################################## # Prompt the user with the given prompt ($1) and make then answer yes/no. # the default answer is arg $2 # # Return 0 if answer is y, 1 if answer is n. # get_y_n_response() { prompt=$1 def_ans=$2 while : do echo "$prompt\c" [ "$def_ans" = "y" ] && echo " ([y]/n) \c" [ "$def_ans" = "n" ] && echo " (y/[n]) \c" read resp case $resp in y|yes) return 0;; n|no) return 1;; "") [ "$def_ans" = "y" ] && return 0 [ "$def_ans" = "n" ] && return 1 ;; *) echo "Please respond \"y\" or \"n\"." esac done } ########################################################################## # setup_rhost() # # If a system cannot be contacted, then this routine is used to # interactively prompt for a passwd and then setup the .rhosts # file on the client to let us reboot it. # # Returns 0 if the user tried to setup .rhosts and the caller should # try the remsh again. Return 1 if the user wants to blow of the client. # # Some globals used by setup_rhost - uses get_ip_addr this_host="$(hostname)" this_host_wdomain="$(get_full_name $(hostname))" this_ip="$(get_ip_addr $this_host)" setup_rhost() { host=$1 host_ip=$2 if get_y_n_response "\n\ The target system \"$host\", is not allowing root remsh access by you ($this_user@$this_host). Would you like bootsys to set the .rhosts file on that system at this time?" "y" then # Create the .rhost entry - with both hostname & IP addr in # case the client is unable to lookup this host. # rexec will prompt for a passwd and does not require .rhosts # Put outout to stdout so that ignite GUI does not misinterpret # a passwd failure as a bootsys failure. rexec $host_ip -l root "echo \"$this_host $this_user\n$this_host_wdomain $this_user\n$this_ip $this_user\" >> .rhosts" 2>&1 echo "Will retry remsh now." return 0 else return 1 fi } ########################################################################## # Determine given the "model" command output from the client, # if the system requires the "VINSTALL" kernel # uses_V_kernel() { case $1 in 9000/8*/V*) return 0 ;; *) return 1 ;; esac } ########################################################################## # hang_guard: # # Run the given command ($1) with timeout ($2 seconds) and make sure we # do not hang on the command. Very useful when doing remsh/rcp to # a system that may not be responding and we don't want to hang on it. # # This function does not work when called as a subprocess unfortunately # (meaning as part of a pipe, or when capturing output) # hang_timeout_handler() { # Do nothing, just being called causes us to break out of the wait # on a hung background process : } hang_guard() { if [ "$1" = "" -o "$2" = "" ] ; then echo "usage: hang_guard " return 1 fi hang_guard_pid="$$" # # Setup a trap handler that just breaks us out of the wait for # the process we put in the background. # trap hang_timeout_handler SIGUSR1 (sleep $2; kill -SIGUSR1 $hang_guard_pid) & sleeper_pid=$! # Run then given command in the background: eval $1 & # Now wait for the background process, if it is hung then # the hang_timeout_handler will be called and break us out wait $! wait_ret=$? # Terminate the sleeping hang protector. kill -TERM $sleeper_pid trap "" SIGUSR1 if ps -p $! >/dev/null then wait_ret=1 echo "Command \"$1\" appears hung, killing it." >&2 # # Get the PID of the last background process and all # it's children - since the "eval" statement causes # a subshell. # pids=$(ps -ef | awk '{if ($3 == '$!') printf("%s ", $2)}') kill -HUP $! $pids ps -p "$pids" >/dev/null && sleep 1 && kill -TERM $pids && \ ps -p "$pids" >/dev/null && sleep 2 && kill -9 $pids && sleep 1 if ps -p "$pids" >/dev/null then echo "Command: \"$1\" will not die, leaving it in background." >&2 fi fi return $wait_ret } ########################################################################## # MAIN: # if [ ! -f $LOGFILE ] ; then touch $LOGFILE >/dev/null 2>&1 fi if [ -w $LOGFILE ] ; then echo "bootsys start: (pid: $$) $(date)" >> $LOGFILE echo "\t($$) Called with options: \"$*\"" >> $LOGFILE fi while getopts :awdvhrfi:s: opt do case "$opt" in i) cfg="$OPTARG";; s) shutdown_grace="$OPTARG";; a) auto_mode=true;; w) wait_mode=true;; d) d_opt=true;; h) h_opt=true;; r) r_opt=true;; f) f_opt=true;; v) verbose=true;; "?") echo "Unrecognized option: \"-$OPTARG\"" >&2 if [ -w $LOGFILE ] ; then echo "\t($$) Unrecognized option: \"-$OPTARG\"">> $LOGFILE fi echo "$usage" >&2 exit_val=1 exit 1;; ":") echo "Argument missing to option: \"-$OPTARG\"" >&2 if [ -w $LOGFILE ] ; then echo "\t($$) Argument missing to option: \"-$OPTARG\"">> $LOGFILE fi echo "$usage" >&2 exit_val=1 exit 1;; esac done if [ ! -w $LOGFILE ] ; then [ $verbose = true ] && echo "\tLogging disabled, no permission for: $LOGFILE" fi # Shift past recognized optins ((OPTIND -= 1)) shift $OPTIND if [ $# -eq 0 ] ; then echo "No clients names provided" >&2 if [ -w $LOGFILE ] ; then echo "\t($$) No clients names provided">> $LOGFILE fi echo "$usage" >&2 exit_val=1 exit 1 fi # # Initialize arrays to hold information for each client for arg in $* do release[$num_clients]="unknown" status[$num_clients]="ok" client[$num_clients]="${arg%%:*}" # strip off any alternate IP if [ "${client[$num_clients]%%[0-9]*}" = "" ] ; then echo "ERROR: Invalid client name: \"${client[$num_clients]}\".\n\tIf you wish to use an IP address, you must supply both the client's\n\thostname and IP address using the syntax: client:IP" >&2 exit 1 fi client_cur_ip[$num_clients]="$(get_ip_addr ${arg%%:*})" if [ "${client_cur_ip[$num_clients]}" = "" -a "$h_opt" = false ] ; then if [ "${arg%%:*}" != "${arg##*:}" ] ; then # Could not lookup the IP address, but the IP was given # on the command line, so assume that is correct. client_cur_ip[$num_clients]="${arg##*:}" else status[$num_clients]="Cannot lookup IP address for \"$arg\"" fi fi if [ "${arg%%:*}" != "${arg##*:}" ] ; then client_ip[$num_clients]="${arg##*:}" if [ "$h_opt" = true ] ; then echo "\ WARNING: Specifying an IP address for client \"$arg\" has no effect since the -h option is given." >&2 fi else client_ip[$num_clients]=${client_cur_ip[$num_clients]} fi # # Check to see if the server is listed in the clients, just check # The base hostname (ignore domain since $this_host is usually # just the base part). # if [ "${client[$num_clients]%%.*}" = ${this_host%%.*} ] ; then echo "ERROR: You listed the Ignite-UX server ($this_host) to be rebooted." >&2 exit_val=1 exit 1 fi ((num_clients += 1)) done if [ $auto_mode = "true" -a $wait_mode = "true" ] ; then echo "Cannot specify both -a and -w options" >&2 echo "$usage" >&2 exit_val=1 exit 1 fi # # Check to see if any cfg argument exists in the INDEX files # Note that manage_index always gives a 0 exit - which may change, # so for now check for any output - if none, then it is a bad cfg. # if [ "$cfg" != "" ] ; then output=$(manage_index -l -c "$cfg") if [ "$?" != 0 -o "$output" != "$cfg" ] ; then echo "Undefined configuration \"$cfg\" specified with -i option." >&2 exit_val=1 exit 1 fi fi for f in $INSTALL $INSTALLFS do if [ ! -f $f ] ; then echo "Cannot access server file: \"$f\" - is Ignite-UX installed?" >&2 exit_val=1 exit 1 fi done # # Determine how much free space is needed in the /stand volume # on the client. Amount is in KB, plus 32KB as breathing room. # typeset -i space_needed v_space_needed free_space space_needed=$(du -s $INSTALL $INSTALLFS | awk 'BEGIN {sum=0} {sum+= ($1 / 2)} END{print sum + 32}') [ $verbose = true ] && echo "\tSpace required in /stand: ${space_needed} KB" if [ -f $VINSTALL -a -f $VINSTALLFS ] then # Note the traiing "/" on VINSTALLFS - it is a symlink, and this # to to get the link followed. v_space_needed=$(du -s $VINSTALL $VINSTALLFS/ | awk 'BEGIN {sum=0} {sum+= ($1 / 2)} END{print sum + 32}') [ $verbose = true ] && echo "\tSpace required in /stand for V-Class: ${v_space_needed} KB" else v_space_needed=0 fi # # Gather release information about each client. # while [ $cn -lt $num_clients ] ; do if [ "${status[$cn]}" != "ok" -a "${status[$cn]}" != "kernel cleaning" ] then ((cn += 1)) continue # Skip problem clients fi [ $verbose = true ] && echo "\tGetting information for \"${client[$cn]}\"" # # Check to see if the system is alive # if ping ${client_cur_ip[$cn]} -n 1 2>&1 | fgrep -q "0 packets received" then status[$cn]="Cannot ping system, probably down." ((cn += 1)) continue fi # Use a hang-protected remsh to get the uname value from client, # and to check if the client is allowing remsh access. # Allow 60 seconds for the command to work before giving up hang_guard "remsh ${client_cur_ip[$cn]} -l root -n uname -r" 60 > $tmp_output 2>&1 if [ $? != 0 ] ; then output="$(cat $tmp_output)" if [ "${output%%Login incorrect*}" != "$output" ] ; then # Remote system is lacking .rhosts permission. if [ "$d_opt" = "false" ] ; then if setup_rhost ${client[$cn]} ${client_cur_ip[$cn]} ; then continue # try the remsh again - otherwise fail the client fi fi fi status[$cn]="remsh error: $output" ((cn += 1)) continue else release[$cn]="$(cat $tmp_output)" fi rm -f $blk_tmp rcp root@${client_cur_ip[$cn]}:/.bootsys_block $blk_tmp >/dev/null 2>&1 if [ -f $blk_tmp ] ; then if [ -s $blk_tmp ] ; then read blk_key junk < $blk_tmp wc -l $blk_tmp | read lines junk if [ "$blk_key" = "confirm" -a $lines -gt 1 ] || [ "$blk_key" != "confirm" ] ; then echo "\ The target client: \"${client[$cn]}\" is blocking installation via bootsys for the following reason: ================================================================" if [ "$blk_key" = "confirm" ] ;then tail +2 $blk_tmp else cat $blk_tmp fi echo "\ ================================================================" fi if [ "$blk_key" = "confirm" ] ; then if [ "$d_opt" = "true" ] ; then echo "\ The target client: \"${client[$cn]}\" is requesting confirmation before installation. Since -d option was given, the client will be skipped." status[$cn]="Client is blocking bootsys via /.bootsys_block file." ((cn += 1)) continue fi echo "The client \"${client[$cn]}\" requests that you confirm any attempts to reinstall it." if get_y_n_response "Do you really wish to reinstall \"${client[$cn]}\"?" "n" then if [ -w $LOGFILE ] ; then echo "\t($$) User confirmed that they want to install \"${client[$cn]}\"" >> $LOGFILE fi else status[$cn]="Client is blocking bootsys via /.bootsys_block file." ((cn += 1)) continue fi else status[$cn]="Client is blocking bootsys via /.bootsys_block file." ((cn += 1)) continue fi else # $blk_tmp exists and is empty: status[$cn]="Client is blocking bootsys via /.bootsys_block file." ((cn += 1)) continue fi rm -f $blk_tmp fi # # Now copy the bootsys_prep script which we use to get some LAN # and other info from the client # rcp $bootsys_prep root@${client_cur_ip[$cn]}:/tmp/bootsys_prep if [ $? != 0 ] ; then status[$cn]="rcp error on $bootsys_prep" ((cn += 1)) continue fi case ${release[$cn]} in *9.??) remote_shell=/bin/ksh ;; *10.*|*11.*) remote_shell=/sbin/sh ;; *) status[$cn]="Unsupported release (${release[$cn]}), or error getting uname value." ((cn += 1)) continue esac remsh ${client_cur_ip[$cn]} -l root -n "$remote_shell /tmp/bootsys_prep -n ${client_cur_ip[$cn]}" | read iface lla default_route hw_path free_space netmask sys_model if [ "$iface" = "" -o "$lla" = "" ] ; then status[$cn]="Error obtaining system information." ((cn += 1)) continue fi client_iface[$cn]="$iface" client_lla[$cn]="$lla" client_hw_path[$cn]="$hw_path" client_sys_model[$cn]="$sys_model" if [ "$default_route" != "n/a" ] ; then client_route[$cn]="$default_route" else client_route[$cn]="" fi if [ "$netmask" != "n/a" ] ; then client_netmask[$cn]="$netmask" else client_netmask[$cn]="" fi if uses_V_kernel ${client_sys_model[$cn]} then kern_space=$v_space_needed else kern_space=$space_needed fi # # Check for sufficient disk space as reported by the client: # if [ "$kern_space" -gt $free_space ]; then if [ "${status[$cn]}" = "kernel cleaning" ] then status[$cn]="Insufficient disk space in /stand directory (need ${kern_space}KB, has ${free_space}KB." ((cn += 1)) continue else echo "\tAttempting to free up disk space in /stand on \"${client[$cn]}\"" status[$cn]="kernel cleaning" remsh ${client_cur_ip[$cn]} -l root -n "rm -rf /stand/vmunix.prev /stand/dlkm.vmunix.prev" continue # try this client again to see if that was enough. fi else status[$cn]="ok" fi [ $verbose = true ] && echo "\tclient: \"${client[$cn]}\" current OS: \"${release[$cn]}\" \t\tip_addr: \"${client_ip[$cn]}\" lan_interface: \"${client_iface[$cn]}\" \t\tLLA: \"${client_lla[$cn]}\" default_route: \"${client_route[$cn]}\" \t\tnetmask: \"${client_netmask[$cn]}\" \t\troot HW path: \"${client_hw_path[$cn]}\" space in /stand: ${free_space} KB \t\tstatus: \"${status[$cn]}\" model: \"${client_sys_model[$cn]}\"\n" ((cn += 1)) done ########################################################################## # Check for any errors from doing remsh's to each system to get release # value # cn=0 errs=0 while [ $cn -lt $num_clients ] ; do if [ "${status[$cn]}" != "ok" ] ; then echo "Fatal error on \"${client[$cn]}\": (${status[$cn]})">&2 if [ -w $LOGFILE ] ; then echo "\t($$) Fatal error on \"${client[$cn]}\": (${status[$cn]})">> $LOGFILE fi status[$cn]="reported" ((errs += 1)) fi ((cn += 1)) done if [ $errs -gt 0 ] ; then if [ "$d_opt" = "false" -a $num_clients -gt 1 ] ; then echo "Specify -d option if you wish to ignore inaccessible clients">&2 if [ -w $LOGFILE ] ; then echo "\t($$) Specify -d option if you wish to ignore inaccessible clients">> $LOGFILE fi exit_val=1 exit 1 elif [ $num_clients -eq 1 ] ; then exit 1 fi fi [ $verbose = true ] && echo "" # newline separator # # Now check that index cfg is matching what a client has - or that # we can remove the client's prior config file. # cn=0 while [ $cn -lt $num_clients ] ; do if [ "${status[$cn]}" != "ok" ] ; then ((cn += 1)) continue # Skip problem clients fi config_file="/var/opt/ignite/clients/${client_lla[$cn]}/config" if [ "$f_opt" = "true" -a -f $config_file ] ; then [ $verbose = true ] && echo "\tRemoving $config_file (-f option)" rm -f $config_file if [ -f $config_file ] ; then echo "Cannot remove: $config_file" >&2 if [ -w $LOGFILE ] ; then echo "\t($$) Cannot remove: $config_file">> $LOGFILE fi exit_val=1 exit 1 fi fi config_file="/var/opt/ignite/clients/history/${client_lla[$cn]}/config" if [ "$f_opt" = "true" -a -f $config_file ] ; then [ $verbose = true ] && echo "\tNull'ing $config_file (-f option)" echo > $config_file # clobber the file. if [ $? != 0 ] ; then echo "Cannot empty: $config_file" >&2 if [ -w $LOGFILE ] ; then echo "\t($$) Cannot empty: $config_file">> $LOGFILE fi exit_val=1 exit 1 fi fi for config_file in /var/opt/ignite/clients/${client_lla[$cn]}/config \ /var/opt/ignite/clients/history/${client_lla[$cn]}/config do if [ "$cfg" != "" ] ; then # # Make sure that if there is a client config file, that # the cfg statement in in matches what is being specifed here. # if [ -f $config_file ] then cfg_line=$(grep "cfg.*=[ \t]*[Tt]" $config_file | grep -v "^[ \t]*#") if [ "$cfg_line" != "" ] ; then if echo "$cfg_line" | fgrep -q "$cfg" then : # this is okay else msg="\ ERROR: Client \"${client[$cn]}\" has configuration information in \t$config_file that conflicts with the -i option. \tUse the -f option to bootsys to cause removal this file if you wish." echo "$msg" >&2 if [ -w $LOGFILE ] ; then echo "($$) $msg">> $LOGFILE fi exit_val=1 exit 1 fi fi fi else if [ "$verbose" = true -a -f $config_file ] ; then cfg_line=$(grep "cfg.*=[ \t]*[Tt]" $config_file) echo "\tUsing configuration for ${client[$cn]} ($cfg_line)" break; # don't check the history file. fi fi done ((cn += 1)) done instl_adm -d > $tmp_cfg_file || exit 1 to_be_removed="$to_be_removed $tmp_cfg_file" if [ "$auto_mode" = "true" ] ; then echo "run_ui=false\ncontrol_from_server=false" >> $tmp_cfg_file fi if [ "$wait_mode" = "true" ] ; then echo "run_ui=false\ncontrol_from_server=true" >> $tmp_cfg_file fi # # If hide_boot_disk=true in the INSTALLFS, then override it in the # copy we send to the client or else the client will not be able to # install to the currently booted disk, which is probably not the # intended usage. # if grep -q "hide_boot_disk[ =]*[tT][rR][uU][eE]" $tmp_cfg_file then echo "hide_boot_disk=false" >> $tmp_cfg_file echo "NOTE: Overriding current hide_boot_disk setting." if [ -w $LOGFILE ] ; then echo "NOTE: Overriding current hide_boot_disk setting." >> $LOGFILE fi fi ########################################################################## # Copy the kernel and filesystem over to the client. # # Note: THis could be done in parallel for each client in the future # cn=0 errs=0 while [ $cn -lt $num_clients ] ; do if [ "${status[$cn]}" != "ok" ] ; then ((cn += 1)) continue # Skip problem clients fi client_cfg_data="" # Get the IP address of client to stick in cfg file # always set the cur_lan_dev - because dhcp will even need to # have that set to know which device to go out on. client_cfg_data="${client_cfg_data}_hp_default_cur_lan_dev=\"${client_iface[$cn]}\"\n" if [ $h_opt = false ] ; then client_cfg_data="${client_cfg_data}system_name=\"${client[$cn]%%.*}\"\nip_addr[]=\"${client_ip[$cn]}\"\n" if [ "${client_netmask[$cn]}" != "" ] ; then client_cfg_data="${client_cfg_data}netmask[]=\"${client_netmask[$cn]}\"\n" fi if [ "${client_route[$cn]}" != "" ] ; then client_cfg_data="${client_cfg_data}route_gateway[0]=\"${client_route[$cn]}\"\nroute_destination[0]=\"default\"\n" fi fi if [ "$cfg" != "" ] ; then client_cfg_data="${client_cfg_data}cfg \"$cfg\"=TRUE\n" fi if grep -q INST_ALLOW_WARNINGS $tmp_cfg_file then : else # # Set system to allow warnings after some amount of timeout. # client_cfg_data="$client_cfg_data env_vars +=\"INST_ALLOW_WARNINGS=$warning_timeout_value\"\n" fi cp $tmp_cfg_file ${tmp_cfg_file}.${client[$cn]} echo "$client_cfg_data" >> ${tmp_cfg_file}.${client[$cn]} to_be_removed="$to_be_removed ${tmp_cfg_file}.${client[$cn]}" # # Check to ensure that the added data to the config file does not push # it over the 8K limit - bail out if so and let the user know how to fix # it. # wc -c ${tmp_cfg_file}.${client[$cn]} | read size junk if [ "$size" -gt 8192 ] ; then msg="\ ERROR: Could not add required information to the 8K config file region of the INSTALLFS file because the resulting config file is over 8K. To fix this problem, you will need to reduce the size of the existing data stored in this area via the instl_adm -d/-f command. Must reduce by $(expr $size - 8192) bytes." echo "$msg" >&2 if [ -w $LOGFILE ] ; then echo "($$) $msg">> $LOGFILE fi exit_val=1 exit 1 fi if uses_V_kernel ${client_sys_model[$cn]} then ikern=$VINSTALL iramfs=$VINSTALLFS else ikern=$INSTALL iramfs=$INSTALLFS fi [ $verbose = true ] && echo "\tCopying $ikern & $iramfs to ${client[$cn]}" # # The complex use of subshells and dd is to insert thew new cfg file # into the first 8k of INSTALLFS as it goes over the wire. This allows # us to not have to apply the changes one at a time to the INSTALLFS # beforehand. # ( dd if=${tmp_cfg_file}.${client[$cn]} bs=8k conv=sync count=1 2>/dev/null dd if=$iramfs bs=8k skip=1 2>/dev/null ) | remsh ${client_cur_ip[$cn]} -l root "mkdir -p /stand; cat > /stand/INSTALLFS" if [ $? != 0 ] ; then status[$cn]="remsh error." ((errs += 1)) ((cn += 1)) continue fi rcp $ikern root@${client_cur_ip[$cn]}:/stand/INSTALL if [ $? != 0 ] ; then status[$cn]="rcp error on $ikern" ((errs += 1)) ((cn += 1)) continue fi prep_opts="" case ${release[$cn]} in *9.??) # Copy the boot_lif for use by mkboot rcp $boot_lif root@${client_cur_ip[$cn]}:/tmp/boot_lif if [ $? != 0 ] ; then status[$cn]="rcp error on $boot_lif" ((errs += 1)) ((cn += 1)) continue fi prep_opts="-b /tmp/boot_lif" remote_shell=/bin/ksh ;; *) remote_shell=/sbin/sh ;; esac if [ "$r_opt" = true ] ; then # Add the no-reboot option to bootsys_prep prep_opts="$prep_opts -r" fi if [ "$shutdown_grace" != "" ] ; then # propagate the -s option prep_opts="$prep_opts -s $shutdown_grace" fi if [ "$verbose" = true ] ; then # Add the verbose option to bootsys_prep prep_opts="$prep_opts -v" fi # # Use bootsys_prep to prepare the client to reboot and to reboot it. # Use the $remote_shell variable to ensure we get a posix/ksh. Because # it is different for 9.X and 10.X systems - must be explicit # if [ "${status[$cn]}" = "ok" ] ; then if [ -w $LOGFILE ] ; then echo "\t($$) === Preparing system: ${client[$cn]}" >> $LOGFILE remsh ${client_cur_ip[$cn]} -l root -n "$remote_shell /tmp/bootsys_prep $prep_opts" 2>&1 | tee -a $LOGFILE else remsh ${client_cur_ip[$cn]} -l root -n "$remote_shell /tmp/bootsys_prep $prep_opts" fi [ $verbose = true ] && echo "" # newline to separate system info fi rm -f ${tmp_cfg_file}.${client[$cn]} ((cn += 1)) done rm -f $tmp_cfg_file cn=0 while [ $cn -lt $num_clients ] ; do if [ "${status[$cn]}" != "ok" -a "${status[$cn]}" != "reported" ] ; then msg="Fatal error on \"${client[$cn]}\": (${status[$cn]})" echo "$msg" >&2 if [ -w $LOGFILE ] ; then echo "($$) $msg">> $LOGFILE fi fi ((cn += 1)) done exit_val=$errs exit $errs