#!/sbin/sh # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)install-recovery.sh 1.2 06/03/21 SMI" # # This script looks for installed Solaris instances to facilitate # user recovery of corrupt rootfs # validate_ckyorn() { if [ $1 = y ] || [ $1 = Y ] || [ $1 = yes ] || [ $1 = Yes ] || \ [ $1 = yEs ] || [ $1 = YEs ] || [ $1 = yeS ] || [ $1 = YeS ] || \ [ $1 = yES ] || [ $1 = YES ] ; then echo y else echo n fi } update_archive() { dev=$1 printf "\nAn out of sync boot archive was detected on $dev.\n" printf "The boot archive is a cache of files used during boot and\n" printf "should be kept in sync to ensure proper system" printf " operation.\n" help="This will fsck if needed, mount, and update the boot archive" prompt="Do you wish to automatically update this boot archive?" ans=`/usr/bin/ckyorn -Q -p "${prompt}" -h "${help}"` ans=`validate_ckyorn $ans` if [ "$ans" = "y" ] ; then umount /a 2> /dev/null fsck_and_mount $dev echo Updating boot archive on $dev. bootadm update-archive -R /a > /dev/null # If bootadm fails, it's pretty verbose on stderr. If it # succeeds, it is silent. In this case however, clear # positive indication of success is desirable: if [ $? = 0 ] ; then echo The boot archive on $dev was updated successfully. fi umount /a fi } update_md_msg() { printf "To manually recover the boot archive on a root mirror," printf "mount the first\nside (the one that the system boots from)" printf " and run:\n\n\tbootadm update-archive -R " printf "\n\n" } find_OS_roots() { for Dev in /dev/dsk/*s[0-7]; do Typ=`/usr/sbin/fstyp $Dev 2> /dev/null` if [ "X${Typ}" = Xufs ]; then /sbin/mount -o ro -F ufs $Dev /a status=$? if [ ${status} != 0 ]; then echo "Failed to mount $Dev read-only: skipping." continue; fi if [ -f /a/etc/release ]; then /sbin/bootadm update-archive -n -R /a \ > /dev/null 2>&1 if [ $? = 0 ] ; then ARCHIVE=synced else ARCHIVE=faulted fi # Check if this root is under md control. # If it is, leave it alone. MD=`grep "[ ]/[ ]" /a/etc/vfstab | \ grep "^/dev/md"` if [ -n "$MD" ] ; then echo $Dev is under md control, skipping. if [ $ARCHIVE = faulted ] ; then update_md_msg fi umount /a continue; fi OS_found=`expr $OS_found + 1` rel=`sed -n '1s/^ *//p' /a/etc/release` if [ $ARCHIVE = faulted ] ; then update_archive $Dev fi echo $rel >> $rel_list OS_rootdevs="$OS_rootdevs $Dev" fi umount /a 2> /dev/null fi done } fsck_and_mount() { dsk=$1 rdsk=`echo $dsk | sed "s#/dsk/#/rdsk/#"` fsck -m -F ufs $rdsk > /dev/null 2>&1 if [ $? != 0 ] ; then fsck -F ufs $rdsk fi umount /a 2> /dev/null mount $dsk /a } OS_found=0 OS_rootdevs= rel_list=/tmp/rel_list.$$ mnthelp="Check and mount the selected root device read-write." mntprompt="Do you wish to have it mounted read-write on /a?" echo "Searching for installed OS instances..." find_OS_roots if [ $OS_found -eq 0 ]; then echo "No installed OS instance found." elif [ $OS_found -eq 1 ]; then dev=`echo $OS_rootdevs` rel=`cat $rel_list` printf "\n$rel was found on $dev." ans=`/usr/bin/ckyorn -Q -p "${mntprompt}" -h "${mnthelp}"` ans=`validate_ckyorn $ans` if [ "$ans" = "y" ] ; then echo "mounting $dev on /a" fsck_and_mount $dev fi else printf "\nMultiple OS instances were found. To check and mount " printf "one of them\nread-write under /a, select it from the " printf "following list. To not mount\nany, select 'q'.\n" item=1 itemlist=/tmp/itemlist_$$ rm -f $itemlist for dev in $OS_rootdevs ; do rel=`head -$item $rel_list | tail -1` printf "$dev\t$rel\n" >> $itemlist item=`expr $item + 1` done prompt="Please select a device to be mounted (q for none)" dev=`/usr/bin/ckitem -p "${prompt}" -h "${mnthelp}" -f $itemlist` rm $itemlist if [ "$dev" != "q" ] ; then echo "mounting $dev on /a" fsck_and_mount $dev break fi fi rm -f $rel_list printf "\nStarting shell.\n" /sbin/sulogin