17c478bd9Sstevel@tonic-gate#!/sbin/sh 27c478bd9Sstevel@tonic-gate# 37c478bd9Sstevel@tonic-gate# CDDL HEADER START 47c478bd9Sstevel@tonic-gate# 57c478bd9Sstevel@tonic-gate# The contents of this file are subject to the terms of the 67c478bd9Sstevel@tonic-gate# Common Development and Distribution License, Version 1.0 only 77c478bd9Sstevel@tonic-gate# (the "License"). You may not use this file except in compliance 87c478bd9Sstevel@tonic-gate# with the License. 97c478bd9Sstevel@tonic-gate# 107c478bd9Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 117c478bd9Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing. 127c478bd9Sstevel@tonic-gate# See the License for the specific language governing permissions 137c478bd9Sstevel@tonic-gate# and limitations under the License. 147c478bd9Sstevel@tonic-gate# 157c478bd9Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each 167c478bd9Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 177c478bd9Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the 187c478bd9Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying 197c478bd9Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner] 207c478bd9Sstevel@tonic-gate# 217c478bd9Sstevel@tonic-gate# CDDL HEADER END 227c478bd9Sstevel@tonic-gate# 237c478bd9Sstevel@tonic-gate# 24943287c6SIgor Kozhukhov# Copyright 2012 Nexenta Sysytems, Inc. All rights reserved. 258918dff3Sjwadams# Copyright 2005 Sun Microsystems, Inc. All rights reserved. 267c478bd9Sstevel@tonic-gate# Use is subject to license terms. 277c478bd9Sstevel@tonic-gate# 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gatePATH=/sbin:/usr/bin:/usr/sbin 308918dff3SjwadamsLC_ALL=C 318918dff3Sjwadamsexport PATH LC_ALL 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate. /lib/svc/share/smf_include.sh 347c478bd9Sstevel@tonic-gate. /lib/svc/share/fs_include.sh 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gateusage() 377c478bd9Sstevel@tonic-gate{ 387c478bd9Sstevel@tonic-gate echo "usage: $0 [-r rootdir]" >&2 398918dff3Sjwadams echo " 40654b400cSJoshua M. ClulowSee http://illumos.org/msg/SMF-8000-MY for more information on the use of 418918dff3Sjwadamsthis script." 427c478bd9Sstevel@tonic-gate exit 2; 437c478bd9Sstevel@tonic-gate} 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gaterepositorydir=etc/svc 467c478bd9Sstevel@tonic-gaterepository=repository 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gatemyroot=/ 497c478bd9Sstevel@tonic-gatewhile getopts r: opt; do 507c478bd9Sstevel@tonic-gate case "$opt" in 517c478bd9Sstevel@tonic-gate r) myroot=$OPTARG 527c478bd9Sstevel@tonic-gate if [ ! -d $myroot ]; then 537c478bd9Sstevel@tonic-gate echo "$myroot: not a directory" >&2 547c478bd9Sstevel@tonic-gate exit 1 557c478bd9Sstevel@tonic-gate fi 567c478bd9Sstevel@tonic-gate # validate directory and make sure it ends in '/'. 577c478bd9Sstevel@tonic-gate case "$myroot" in 587c478bd9Sstevel@tonic-gate //*) echo "$myroot: must begin with a single /" >&2 597c478bd9Sstevel@tonic-gate usage;; 607c478bd9Sstevel@tonic-gate /) echo "$myroot: alternate root cannot be /" >&2 617c478bd9Sstevel@tonic-gate usage;; 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate /*/) ;; # ends with / 647c478bd9Sstevel@tonic-gate /*) myroot="$myroot/";; # add final / 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate *) echo "$myroot: must be a full path" >&2 677c478bd9Sstevel@tonic-gate usage;; 687c478bd9Sstevel@tonic-gate esac;; 697c478bd9Sstevel@tonic-gate ?) usage;; 707c478bd9Sstevel@tonic-gate esac 717c478bd9Sstevel@tonic-gatedone 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gateif [ $OPTIND -le $# ]; then 747c478bd9Sstevel@tonic-gate # getopts(1) didn't slurp up everything. 757c478bd9Sstevel@tonic-gate usage 767c478bd9Sstevel@tonic-gatefi 777c478bd9Sstevel@tonic-gate 788918dff3Sjwadams# 798918dff3Sjwadams# Note that the below test is carefully constructed to fail *open*; if 808918dff3Sjwadams# anything goes wrong, it will drive onward. 818918dff3Sjwadams# 828918dff3Sjwadamsif [ -x /usr/bin/id -a -x /usr/bin/grep ] && 838918dff3Sjwadams /usr/bin/id 2>/dev/null | /usr/bin/grep -v '^[^=]*=0(' >/dev/null 2>&1; then 848918dff3Sjwadams echo "$0: may only be invoked by root" >&2 858918dff3Sjwadams exit 2 868918dff3Sjwadamsfi 878918dff3Sjwadams 888918dff3Sjwadamsecho >&2 " 89654b400cSJoshua M. ClulowSee http://illumos.org/msg/SMF-8000-MY for more information on the use of 90*bbf21555SRichard Lowethis script to restore backup copies of the smf(7) repository. 918918dff3Sjwadams 928918dff3SjwadamsIf there are any problems which need human intervention, this script will 938918dff3Sjwadamsgive instructions and then exit back to your shell." 948918dff3Sjwadams 95943287c6SIgor Kozhukhovif [ "$myroot" = "/" ]; then 967c478bd9Sstevel@tonic-gate system="system" 977c478bd9Sstevel@tonic-gate [ "`/sbin/zonename`" != global ] && system="zone" 987c478bd9Sstevel@tonic-gate echo >&2 " 997c478bd9Sstevel@tonic-gateNote that upon full completion of this script, the $system will be rebooted 100*bbf21555SRichard Loweusing reboot(8), which will interrupt any active services. 1017c478bd9Sstevel@tonic-gate" 1027c478bd9Sstevel@tonic-gatefi 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate# check that the filesystem is as expected 1057c478bd9Sstevel@tonic-gatecd "$myroot" || exit 1 1067c478bd9Sstevel@tonic-gatecd "$myroot$repositorydir" || exit 1 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gatenouser=false 1097c478bd9Sstevel@tonic-gaterootro=false 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate# check to make sure /usr is mounted 1127c478bd9Sstevel@tonic-gateif [ ! -x /usr/bin/pgrep ]; then 1137c478bd9Sstevel@tonic-gate nouser=true 1147c478bd9Sstevel@tonic-gatefi 1158918dff3Sjwadams 1167c478bd9Sstevel@tonic-gateif [ ! -w "$myroot" ]; then 1177c478bd9Sstevel@tonic-gate rootro=true 1187c478bd9Sstevel@tonic-gatefi 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gateif [ "$nouser" = true -o "$rootro" = true ]; then 1217c478bd9Sstevel@tonic-gate if [ "$nouser" = true -a "$rootro" = true ]; then 1227c478bd9Sstevel@tonic-gate echo "The / filesystem is mounted read-only, and the /usr" >&2 1237c478bd9Sstevel@tonic-gate echo "filesystem has not yet been mounted." >&2 1247c478bd9Sstevel@tonic-gate elif [ "$nouser" = true ]; then 1257c478bd9Sstevel@tonic-gate echo "The /usr filesystem has not yet been mounted." >&2 1267c478bd9Sstevel@tonic-gate else 1277c478bd9Sstevel@tonic-gate echo "The / filesystem is mounted read-only." >&2 1287c478bd9Sstevel@tonic-gate fi 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate echo >&2 " 1317c478bd9Sstevel@tonic-gateThis must be rectified before $0 can continue. 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gateTo properly mount / and /usr, run: 1347c478bd9Sstevel@tonic-gate /lib/svc/method/fs-root 1357c478bd9Sstevel@tonic-gatethen 1367c478bd9Sstevel@tonic-gate /lib/svc/method/fs-usr 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gateAfter those have completed successfully, re-run: 1397c478bd9Sstevel@tonic-gate $0 $* 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gateto continue. 1427c478bd9Sstevel@tonic-gate" 1437c478bd9Sstevel@tonic-gate exit 1 1447c478bd9Sstevel@tonic-gatefi 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate# at this point, we know / is mounted read-write, and /usr is mounted. 1477c478bd9Sstevel@tonic-gateoldreps="` 1487c478bd9Sstevel@tonic-gate /bin/ls -1rt $repository-*-[0-9]*[0-9] | \ 1497c478bd9Sstevel@tonic-gate /bin/sed -e '/[^A-Za-z0-9_,.-]/d' -e 's/^'$repository'-//' 1507c478bd9Sstevel@tonic-gate`" 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gateif [ -z "$oldreps" ]; then 1537c478bd9Sstevel@tonic-gate cat >&2 <<EOF 1547c478bd9Sstevel@tonic-gateThere are no available backups of $myroot$repositorydir/$repository.db. 1557c478bd9Sstevel@tonic-gateThe only available repository is "-seed-". Note that restoring the seed 1568918dff3Sjwadamswill lose all customizations, including those made by the system during 1578918dff3Sjwadamsthe installation and/or upgrade process. 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gateEOF 1607c478bd9Sstevel@tonic-gate prompt="Enter -seed- to restore from the seed, or -quit- to exit: \c" 1617c478bd9Sstevel@tonic-gate default= 1627c478bd9Sstevel@tonic-gateelse 1637c478bd9Sstevel@tonic-gate cat >&2 <<EOF 1647c478bd9Sstevel@tonic-gateThe following backups of $myroot$repositorydir/$repository.db exist, from 1657c478bd9Sstevel@tonic-gateoldest to newest: 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate$oldreps 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gateThe backups are named based on their type and the time what they were taken. 1707c478bd9Sstevel@tonic-gateBackups beginning with "boot" are made before the first change is made to 1717c478bd9Sstevel@tonic-gatethe repository after system boot. Backups beginning with "manifest_import" 1727c478bd9Sstevel@tonic-gateare made after svc:/system/manifest-import:default finishes its processing. 1737c478bd9Sstevel@tonic-gateThe time of backup is given in YYYYMMDD_HHMMSS format. 1747c478bd9Sstevel@tonic-gate 1758918dff3SjwadamsPlease enter either a specific backup repository from the above list to 1768918dff3Sjwadamsrestore it, or one of the following choices: 1778918dff3Sjwadams 1788918dff3Sjwadams CHOICE ACTION 1798918dff3Sjwadams ---------------- ---------------------------------------------- 1808918dff3Sjwadams boot restore the most recent post-boot backup 1818918dff3Sjwadams manifest_import restore the most recent manifest_import backup 1828918dff3Sjwadams -seed- restore the initial starting repository (All 1838918dff3Sjwadams customizations will be lost, including those 1848918dff3Sjwadams made by the install/upgrade process.) 1858918dff3Sjwadams -quit- cancel script and quit 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gateEOF 1887c478bd9Sstevel@tonic-gate prompt="Enter response [boot]: \c" 1897c478bd9Sstevel@tonic-gate default="boot" 1907c478bd9Sstevel@tonic-gatefi 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gatecont=false 1937c478bd9Sstevel@tonic-gatewhile [ $cont = false ]; do 1947c478bd9Sstevel@tonic-gate echo "$prompt" 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate read x || exit 1 1977c478bd9Sstevel@tonic-gate [ -z "$x" ] && x="$default" 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate case "$x" in 2007c478bd9Sstevel@tonic-gate -seed-) 2017c478bd9Sstevel@tonic-gate if [ $myroot != / -o "`/sbin/zonename`" = global ]; then 2027c478bd9Sstevel@tonic-gate file="$myroot"lib/svc/seed/global.db 2037c478bd9Sstevel@tonic-gate else 2047c478bd9Sstevel@tonic-gate file="$myroot"lib/svc/seed/nonglobal.db 2057c478bd9Sstevel@tonic-gate fi;; 2067c478bd9Sstevel@tonic-gate -quit-) 2077c478bd9Sstevel@tonic-gate echo "Exiting." 2087c478bd9Sstevel@tonic-gate exit 0;; 2097c478bd9Sstevel@tonic-gate /*) 2107c478bd9Sstevel@tonic-gate file="$x";; 2117c478bd9Sstevel@tonic-gate */*) 2127c478bd9Sstevel@tonic-gate file="$myroot$x";; 2137c478bd9Sstevel@tonic-gate ?*) 2147c478bd9Sstevel@tonic-gate file="$myroot$repositorydir/repository-$x";; 2157c478bd9Sstevel@tonic-gate *) file= ;; 2167c478bd9Sstevel@tonic-gate esac 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate if [ -f $file ]; then 2197c478bd9Sstevel@tonic-gate if [ -r $file ]; then 2207c478bd9Sstevel@tonic-gate checkresults="`echo PRAGMA integrity_check\; | \ 2217c478bd9Sstevel@tonic-gate /lib/svc/bin/sqlite $file >&1 | grep -v '^ok$'`" 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate if [ -n "$checkresults" ]; then 2247c478bd9Sstevel@tonic-gate echo "$file: integrity check failed:" >&2 2257c478bd9Sstevel@tonic-gate echo "$checkresults" >&2 2267c478bd9Sstevel@tonic-gate echo 2277c478bd9Sstevel@tonic-gate else 2287c478bd9Sstevel@tonic-gate cont=true 2297c478bd9Sstevel@tonic-gate fi 2307c478bd9Sstevel@tonic-gate else 2317c478bd9Sstevel@tonic-gate echo "$file: not readable" 2327c478bd9Sstevel@tonic-gate fi 2337c478bd9Sstevel@tonic-gate elif [ -n "$file" ]; then 2347c478bd9Sstevel@tonic-gate echo "$file: not found" 2357c478bd9Sstevel@tonic-gate fi 2367c478bd9Sstevel@tonic-gatedone 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gateerrors="$myroot"etc/svc/volatile/db_errors 2397c478bd9Sstevel@tonic-gaterepo="$myroot$repositorydir/$repository.db" 2407c478bd9Sstevel@tonic-gatenew="$repo"_old_"`date +%Y''%m''%d'_'%H''%M''%S`" 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gatesteps= 2437c478bd9Sstevel@tonic-gateif [ "$myroot" = / ]; then 2447c478bd9Sstevel@tonic-gate steps="$steps 245*bbf21555SRichard Lowesvc.startd(8) and svc.configd(8) will be quiesced, if running." 2467c478bd9Sstevel@tonic-gatefi 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gateif [ -r $repo ]; then 2497c478bd9Sstevel@tonic-gate steps="$steps 2507c478bd9Sstevel@tonic-gate$repo 2517c478bd9Sstevel@tonic-gate -- renamed --> $new" 2527c478bd9Sstevel@tonic-gatefi 2537c478bd9Sstevel@tonic-gateif [ -r $errors ]; then 2547c478bd9Sstevel@tonic-gate steps="$steps 2557c478bd9Sstevel@tonic-gate$errors 2567c478bd9Sstevel@tonic-gate -- copied --> ${new}_errors" 2577c478bd9Sstevel@tonic-gatefi 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gatecat >&2 <<EOF 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gateAfter confirmation, the following steps will be taken: 2627c478bd9Sstevel@tonic-gate$steps 2637c478bd9Sstevel@tonic-gate$file 2647c478bd9Sstevel@tonic-gate -- copied --> $repo 2657c478bd9Sstevel@tonic-gateEOF 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gateif [ "$myroot" = / ]; then 268*bbf21555SRichard Lowe echo "and the system will be rebooted with reboot(8)." 2697c478bd9Sstevel@tonic-gatefi 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gateecho 2727c478bd9Sstevel@tonic-gatecont=false 2737c478bd9Sstevel@tonic-gatewhile [ $cont = false ]; do 2747c478bd9Sstevel@tonic-gate echo "Proceed [yes/no]? \c" 2757c478bd9Sstevel@tonic-gate read x || x=n 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate case "$x" in 2787c478bd9Sstevel@tonic-gate [Yy]|[Yy][Ee][Ss]) 2797c478bd9Sstevel@tonic-gate cont=true;; 2807c478bd9Sstevel@tonic-gate [Nn]|[Nn][Oo]) 2817c478bd9Sstevel@tonic-gate echo; echo "Exiting..." 2827c478bd9Sstevel@tonic-gate exit 0; 2837c478bd9Sstevel@tonic-gate esac; 2847c478bd9Sstevel@tonic-gatedone 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gateumask 077 # we want files to be root-readable only. 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gatestartd_msg= 2897c478bd9Sstevel@tonic-gateif [ "$myroot" = / ]; then 2907c478bd9Sstevel@tonic-gate zone="`zonename`" 2917c478bd9Sstevel@tonic-gate startd="`pgrep -z "$zone" -f svc.startd`" 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate echo 294*bbf21555SRichard Lowe echo "Quiescing svc.startd(8) and svc.configd(8): \c" 2957c478bd9Sstevel@tonic-gate if [ -n "$startd" ]; then 2967c478bd9Sstevel@tonic-gate pstop $startd 2977c478bd9Sstevel@tonic-gate startd_msg=\ 298*bbf21555SRichard Lowe"To start svc.start(8) running, do: /usr/bin/prun $startd" 2997c478bd9Sstevel@tonic-gate fi 3007c478bd9Sstevel@tonic-gate pkill -z "$zone" -f svc.configd 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate sleep 1 # yes, this is hack 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate echo "done." 3057c478bd9Sstevel@tonic-gatefi 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gateif [ -r "$repo" ]; then 3087c478bd9Sstevel@tonic-gate echo "$repo" 3097c478bd9Sstevel@tonic-gate echo " -- renamed --> $new" 3107c478bd9Sstevel@tonic-gate if mv $repo $new; then 3117c478bd9Sstevel@tonic-gate : 3127c478bd9Sstevel@tonic-gate else 3137c478bd9Sstevel@tonic-gate echo "Failed. $startd_msg" 3147c478bd9Sstevel@tonic-gate exit 1; 3157c478bd9Sstevel@tonic-gate fi 3167c478bd9Sstevel@tonic-gatefi 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gateif [ -r $errors ]; then 3197c478bd9Sstevel@tonic-gate echo "$errors" 3207c478bd9Sstevel@tonic-gate echo " -- copied --> ${new}_errors" 3217c478bd9Sstevel@tonic-gate if cp -p $errors ${new}_errors; then 3227c478bd9Sstevel@tonic-gate : 3237c478bd9Sstevel@tonic-gate else 3247c478bd9Sstevel@tonic-gate mv -f $new $repo 3257c478bd9Sstevel@tonic-gate echo "Failed. $startd_msg" 3267c478bd9Sstevel@tonic-gate exit 1; 3277c478bd9Sstevel@tonic-gate fi 3287c478bd9Sstevel@tonic-gatefi 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gateecho "$file" 3317c478bd9Sstevel@tonic-gateecho " -- copied --> $repo" 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gateif cp $file $repo.new.$$ && mv $repo.new.$$ $repo; then 3347c478bd9Sstevel@tonic-gate : 3357c478bd9Sstevel@tonic-gateelse 3367c478bd9Sstevel@tonic-gate rm -f $repo.new.$$ ${new}_errors 3377c478bd9Sstevel@tonic-gate mv -f $new $repo 3387c478bd9Sstevel@tonic-gate echo "Failed. $startd_msg" 3397c478bd9Sstevel@tonic-gate exit 1; 3407c478bd9Sstevel@tonic-gatefi 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gateecho 3437c478bd9Sstevel@tonic-gateecho "The backup repository has been successfully restored." 3447c478bd9Sstevel@tonic-gateecho 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gateif [ "$myroot" = / ]; then 3477c478bd9Sstevel@tonic-gate echo "Rebooting in 5 seconds." 3487c478bd9Sstevel@tonic-gate sleep 5 3497c478bd9Sstevel@tonic-gate reboot 3507c478bd9Sstevel@tonic-gatefi 351