#!/bin/csh -f
#
#*s_ssh*************************************************************************
#* AIS lab         	 	C Shell Script     	        SUN-UNIX
#*
#* $Workfile:   online_backup.sh  $ 
#* $Archive:   /tmp_mnt/home/aleis/idb/src/orautil/archives/online_backup.sh_v  $
#*
#* $Author:   dpg  $
#* $Revision:   1.16  $
#* $Date:   01/08/96 09:37:14  $
#* $Modtime:   01/08/96 09:32:26  $
#*
#* Module Description:
#*	
#*      online_backup is used to perform a backup of all data files, 
#*	control files and parameter files associated with a specific 
#*	Oracle instance ("database").  The backup is performed while 
#*	the instance is online and available to other users, so 
#*	productivity is not affected adversely. This utility provides 
#*	generous amounts of information about what is going on at every 
#*	point of its processing.
#*
#* Notes:  
#*
#*	This utility is intended to be used as part of a comprehensive 
#*	backup policy, which would include regularly scheduled filesystem 
#*	backups, online database instance backups, and Oracle archive log 
#*	file backups. A backup policy which is both well thought out and 
#*	carried out is essential to both protecting the data on the system 
#*	and allowing recovery in the event of the loss of file(s) and/or 
#*	filesystem(s).
#*
#*	This utility can only be used by the oracle software owner
#*	(normally the oracle user).
#*
#*	This utility must be executed on the database server node.
#*
#*	The environment must already be set up before this utility is run, 
#*	meaning environment variables such as ORACLE_HOME and IDBHOME must
#*	be correctly set to correspond to the Oracle instance being backed up. 
#* 
#* Copyright (C) 1994-1995 Eastman Kodak Company, All rights reserved 
#*
#*e_ssh*************************************************************************

# Assume: <foo>.sql files are located in a directory contained within the
# 	SQLPATH environment variable
# Assume: shell scripts are located in a directory contained within the 
# 	PATH environment variable
# Assume: config.ora file is located in $HOME/admin/<instance>/pfile,
#	and contains the control_files value with blank lines around it
# Assume: There exists an ops$<oracle-owner> account in the database; this 
#	script is run from the $ORACLE_OWNER SunOS login
# Assume: The ersh command is installed
# Assume: The local0.err facility.level combination is aimed at both the 
#	console and /var/adm/messages in the /etc/syslog.conf file.

setenv ORACLE_SID $1

set ECHO = "/usr/5bin/echo"
set scriptname = "$0"
set to_tape = 0
set alt_to_tape = 0
set alt_present = 0
set to_remote = 0
set remote_host = ""
set alt_to_remote = 0
set alt_remote_host = ""
set backup_successful = 0
set date_string = `date +"%d %h %y"`
set pretty_name = "Online Database Backup ($ORACLE_SID)"
set info_file = "$HOME/online_backup_${ORACLE_SID}.info"

$ECHO "\n\t\t+++ $pretty_name +++\n"

# Have to unsetenv TWO_TASK to allow access to privileged, direct connections
unsetenv TWO_TASK

# Source a script to be used to validate command line arguments
source $IDBHOME/bin/validate_arguments.sh

set exit_status = $status

if ($exit_status) then
        exit $exit_status
endif

if ($to_remote) then
	set fulldest = "${remote_host}:${dest}"
else
	set fulldest = $dest
endif

if ($alt_to_remote) then
	set alt_fulldest = "${alt_remote_host}:${alt_dest}"
else
	set alt_fulldest = $alt_dest
endif

# Verify the instance is running - if it isn't, it's an error
$ECHO "\nVerifying that the Oracle instance is running..."
if ((! -f $ORACLE_HOME/dbs/sgadef${ORACLE_SID}.dbf) && (! -f $ORACLE_HOME/dbs/sgadef${ORACLE_SID}.ora)) then
	$ECHO "\nOracle instance is not running\n"
	/usr/ucb/logger -t "IDB_BACKUP-$ORACLE_SID" -p local0.err "$pretty_name FAILED: Oracle instance is not running"
	exit 21
endif

# Source a script to be used to cleanup, generate file lists
source $IDBHOME/bin/gen_file_lists.sh

# Figure out how much space is needed to backup data files and control files
$ECHO "\nComputing space needed for backup..."
sqlplus -s / @file_sizes
if ($status) then
	goto UNEXPECTED_ERROR
endif
#   (the above command currently generates two files: datafile_size_${ORACLE_SID}.tmp and
#    logfile_size_${ORACLE_SID}.tmp in $HOME)
set datafile_size=`cat $HOME/datafile_size_${ORACLE_SID}.tmp | sed -e "s/ //g"`
if ($status) then
	goto UNEXPECTED_ERROR
endif
# Add 1 MB more for control files
@ total_size = $datafile_size + 1
# Assume we can get at least 50% compression if backing up to disk
@ compressed_size = `expr $total_size / 2`
@ compressed_size = $compressed_size + 1

$ECHO "\tDatafile_size: $datafile_size MB"
$ECHO "\tTotal size: $total_size MB"
$ECHO "\tCompressed size (if to disk): $compressed_size MB"

# Source a script to be used to validate storage capacity
source $IDBHOME/bin/validate_capacity.sh

set exit_status = $status

if ($exit_status) then
        exit $exit_status
endif

# Force an archive log switch to update control file header information
$ECHO "\nSwitching archive logs to force control file update..."
sqlplus -s / @switch_logfile
if ($status) then
	goto UNEXPECTED_ERROR
endif

# start building the tar command...

@ tarfile_count = 1

# remote: to tape: 
#	tar cvfb - 20 <filenames> | ersh $remote_host dd of=$dest obs=20b
# remote: to disk: 
#	tar cvfb - 20 <filenames> | ersh $remote_host (dd obs=20b | compress -fv > ${dest}${tarfile_count}.Z)
# local: to tape: tar cvf $dest
# local: to disk: tar cvf - <files> | compress -fv > ${dest}${tarfile_count}.Z

if ($to_remote) then
	if ($to_tape) then
		set command = "/bin/tar cvfb - 20"
		set pipeline = "| ersh $remote_host /bin/dd of=$dest obs=20b"
	else
		set command = "/bin/tar cvfb - 20"
		set pipeline = "| ersh $remote_host '/bin/dd obs=20b | compress -fv > ${dest}${tarfile_count}.Z'"
	endif
else
	if ($to_tape) then
		set command = "/bin/tar cvbf 20 $dest"
		set pipeline = ""
	else
		set command = "/bin/tar cvbf 20 -"
		set pipeline = "| compress -fv > ${dest}${tarfile_count}.Z"
	endif
endif

$ECHO "\nBeginning backups..."

# Add the various listing files to the backup list

set list1 = "-C $HOME ./tablespaces_${ORACLE_SID}.lst"
foreach tablespace (`cat $HOME/tablespaces_${ORACLE_SID}.lst`)

	set list1 = "$list1 -C $HOME ./files_${ORACLE_SID}_$tablespace.lst"

end
set list1 = "$list1 -C $HOME ./log_files_${ORACLE_SID}.lst -C $HOME ./control_files_${ORACLE_SID}.lst -C $HOME ./parameter_files_${ORACLE_SID}.lst"

set save_command = "$command"

if ((! $to_tape) && (! $save_possible)) then
	$ECHO "\nWarning: Insufficient space in $dest to produce safe backup copies of existing backup files; will overwrite existing files.\n"
	/usr/ucb/logger -t "IDB_BACKUP-$ORACLE_SID" -p local0.err "$pretty_name Warning: Insufficient space in $dest to produce safe backup copies of existing backup files; will overwrite existing files"
endif

if ((! $to_tape) && ($save_possible)) then
	# Make a backup of the file
	set save_file = "${dest}${tarfile_count}.Z"
	if ($to_remote) then
		$ECHO "\nersh $remote_host mv -f" "$save_file" "${save_file}.BAK\n"
		ersh $remote_host mv -f $save_file ${save_file}.BAK
		if ($status) then
			$ECHO "\nUnable to produce safe backup copy of $save_file; continuing\n"
			/usr/ucb/logger -t "IDB_BACKUP-$ORACLE_SID" -p local0.err "$pretty_name Warning: Unable to produce backup copy of $save_file; continuing"
		endif
	else
		$ECHO "\nmv -f" "$save_file" "${save_file}.BAK\n"
		mv -f $save_file ${save_file}.BAK
		if ($status) then
			$ECHO "\nUnable to produce safe backup copy of $save_file; continuing\n"
			/usr/ucb/logger -t "IDB_BACKUP-$ORACLE_SID" -p local0.err "$pretty_name Warning: Unable to produce backup copy of $save_file; continuing"
		endif
	endif
endif
date
$ECHO "\n$command" "$list1" "$pipeline" | fold
/bin/sh -c "$command $list1 $pipeline"
if ($status) then
	$ECHO "\n*** Backup operation failed ***\n"
	goto AFTER_BACKUP
endif
date

# loop through each tablespace

foreach tablespace (`cat $HOME/tablespaces_${ORACLE_SID}.lst`)

	$ECHO "\nProcessing tablespace $tablespace...\n"

	# Put the tablespace into 'BEGIN BACKUP' mode
	sqlplus -s / @ts_begin_backup $tablespace
	if ($status) then
		goto UNEXPECTED_ERROR
	endif

	# Back up each file in the tablespace
	set templist = ""

	foreach file (`cat $HOME/files_${ORACLE_SID}_$tablespace.lst`)

		$ECHO "\tWill backup file $file..."
		
		set templist = "$templist -C $file:h ./$file:t"
	end
	
	@ tarfile_count = $tarfile_count + 1

	if ((! $to_tape) && ($save_possible)) then
		# Make a backup of the file
		set save_file = "$dest${tarfile_count}.Z"
		if ($to_remote) then
			$ECHO "\nersh $remote_host mv -f" "$save_file" "${save_file}.BAK\n"
			ersh $remote_host mv -f $save_file ${save_file}.BAK
			if ($status) then
				$ECHO "\nUnable to produce safe backup copy of $save_file; continuing\n"
				/usr/ucb/logger -t "IDB_BACKUP-$ORACLE_SID" -p local0.err "$pretty_name Warning: Unable to produce backup copy of $save_file; continuing"
			endif
		else
			$ECHO "\nmv -f" "$save_file" "${save_file}.BAK\n"
			mv -f $save_file ${save_file}.BAK
			if ($status) then
				$ECHO "\nUnable to produce safe backup copy of $save_file; continuing\n"
				/usr/ucb/logger -t "IDB_BACKUP-$ORACLE_SID" -p local0.err "$pretty_name Warning: Unable to produce backup copy of $save_file; continuing"
			endif
		endif
	endif
	date

	if ($to_remote) then
		if ($to_tape) then
			set command = "/bin/tar cvfb - 20"
			set pipeline = "| ersh $remote_host /bin/dd of=$dest obs=20b"
		else
			set command = "/bin/tar cvfb - 20"
			set pipeline = "| ersh $remote_host '/bin/dd obs=20b | compress -fv > ${dest}${tarfile_count}.Z'"
		endif
	else
		if ($to_tape) then
			set command = "/bin/tar cvbf 20 $dest"
			set pipeline = ""
		else
			set command = "/bin/tar cvbf 20 -"
			set pipeline = "| compress -fv > ${dest}${tarfile_count}.Z"
		endif
	endif

	$ECHO "\n$command" "$templist" "$pipeline" | fold
	/bin/sh -c "$command $templist $pipeline"
	if ($status) then
		$ECHO "\n*** Backup operation failed ***\n"
		# put the tablespace back online
		sqlplus -s / @ts_end_backup $tablespace
		goto AFTER_BACKUP
	endif
	date

	# put the tablespace back online
	sqlplus -s / @ts_end_backup $tablespace
	if ($status) then
		goto UNEXPECTED_ERROR
	endif
end

# loop through each control file

@ tarfile_count = $tarfile_count + 1
set templist = ""
$ECHO ""

foreach file (`cat $HOME/control_files_${ORACLE_SID}.lst`)

	$ECHO "Will backup control file $file..."
 
	set templist = "$templist -C $file:h ./$file:t" 
end

if ((! $to_tape) && ($save_possible)) then
	# Make a backup of the file
	set save_file = "$dest${tarfile_count}.Z"
	if ($to_remote) then
		$ECHO "\nersh $remote_host mv -f" "$save_file" "${save_file}.BAK\n"
		ersh $remote_host mv -f $save_file ${save_file}.BAK
		if ($status) then
			$ECHO "\nUnable to produce safe backup copy of $save_file; continuing\n"
			/usr/ucb/logger -t "IDB_BACKUP-$ORACLE_SID" -p local0.err "$pretty_name Warning: Unable to produce backup copy of $save_file; continuing"
		endif
	else
		$ECHO "\nmv -f" "$save_file" "${save_file}.BAK\n"
		mv -f $save_file ${save_file}.BAK
		if ($status) then
			$ECHO "\nUnable to produce safe backup copy of $save_file; continuing\n"
			/usr/ucb/logger -t "IDB_BACKUP-$ORACLE_SID" -p local0.err "$pretty_name Warning: Unable to produce backup copy of $save_file; continuing"
		endif
	endif
endif
date

if ($to_remote) then
	if ($to_tape) then
		set command = "/bin/tar cvfb - 20"
		set pipeline = "| ersh $remote_host /bin/dd of=$dest obs=20b"
	else
		set command = "/bin/tar cvfb - 20"
		set pipeline = "| ersh $remote_host '/bin/dd obs=20b | compress -fv > ${dest}${tarfile_count}.Z'"
	endif
else
	if ($to_tape) then
		set command = "/bin/tar cvbf 20 $dest"
		set pipeline = ""
	else
		set command = "/bin/tar cvbf 20 -"
		set pipeline = "| compress -fv > ${dest}${tarfile_count}.Z"
	endif
endif

$ECHO "\n$command" "$templist" "$pipeline" | fold
/bin/sh -c "$command $templist $pipeline"
if ($status) then
	$ECHO "\n*** Backup operation failed ***\n"
	goto AFTER_BACKUP
endif
date

# loop through each parameter file

@ tarfile_count = $tarfile_count + 1
set templist = ""
$ECHO ""

foreach file (`cat $HOME/parameter_files_${ORACLE_SID}.lst`)

	$ECHO "Will backup parameter file $file..."
 
	set templist = "$templist -C $file:h ./$file:t" 
end

if ((! $to_tape) && ($save_possible)) then
	# Make a backup of the file
	set save_file = "$dest${tarfile_count}.Z"
	if ($to_remote) then
		$ECHO "\nersh $remote_host mv -f" "$save_file" "${save_file}.BAK\n"
		ersh $remote_host mv -f $save_file ${save_file}.BAK
		if ($status) then
			$ECHO "\nUnable to produce safe backup copy of $save_file; continuing\n"
			/usr/ucb/logger -t "IDB_BACKUP-$ORACLE_SID" -p local0.err "$pretty_name Warning: Unable to produce backup copy of $save_file; continuing"
		endif
	else
		$ECHO "\nmv -f" "$save_file" "${save_file}.BAK\n"
		mv -f $save_file ${save_file}.BAK
		if ($status) then
			$ECHO "\nUnable to produce safe backup copy of $save_file; continuing\n"
			/usr/ucb/logger -t "IDB_BACKUP-$ORACLE_SID" -p local0.err "$pretty_name Warning: Unable to produce backup copy of $save_file; continuing"
		endif
	endif
endif
date

if ($to_remote) then
	if ($to_tape) then
		set command = "/bin/tar cvfb - 20"
		set pipeline = "| ersh $remote_host /bin/dd of=$dest obs=20b"
	else
		set command = "/bin/tar cvfb - 20"
		set pipeline = "| ersh $remote_host '/bin/dd obs=20b | compress -fv > ${dest}${tarfile_count}.Z'"
	endif
else
	if ($to_tape) then
		set command = "/bin/tar cvbf 20 $dest"
		set pipeline = ""
	else
		set command = "/bin/tar cvbf 20 -"
		set pipeline = "| compress -fv > ${dest}${tarfile_count}.Z"
	endif
endif

$ECHO "\n$command" "$templist" "$pipeline" | fold
/bin/sh -c "$command $templist $pipeline"
if ($status) then
	$ECHO "\n*** Backup operation failed ***\n"
	goto AFTER_BACKUP
endif
date

$ECHO "\nBackup operation complete."

set backup_successful = 1

AFTER_BACKUP:

if ($to_tape) then
	# rewind tape
	$ECHO "\nRewinding tape..."
	if ($to_remote) then
		ersh $remote_host /bin/mt -f $dest rewoffl
	else
		/bin/mt -f $dest rewoffl
	endif
endif

if ($backup_successful) then
	# This is where you would talk about:
	#	remove tape
	#	label
	#	store in a safe place
	
	if ($to_tape) then

		cat <<EOF > $info_file

Once the tape is done rewinding:

	- Remove the tape from the $fulldest tape drive
	- Write-protect the tape
	- Label the tape with the following information:

${pretty_name}: $date_string

Tar format, blocksize 20
	
Tarfile 1: File lists
EOF

		@ counter = 1
		foreach tablespace (`cat tablespaces_${ORACLE_SID}.lst`)
	
			@ counter = $counter + 1
			$ECHO "Tarfile ${counter}: Data files, tablespace $tablespace" >> $info_file
		end
	
		@ counter = $counter + 1
		$ECHO "Tarfile ${counter}: Control files" >> $info_file
	
		@ counter = $counter + 1
		$ECHO "Tarfile ${counter}: Parameter files" >> $info_file
	
		$ECHO "\n\t- Store the tape in a safe location\n" >>$info_file
 
		$ECHO "Please note: If a tarfile other than the first tarfile on" >> $info_file
		$ECHO "the tape needs to be accessed, it will be necessary to" >> $info_file
		$ECHO "'forward-space' the tape to the appropriate file (using the" >> $info_file
		$ECHO "'mt' command) on the tape before the tarfile can be accessed.\n" >> $info_file

		cat $info_file
		/usr/ucb/logger -t "IDB_BACKUP-$ORACLE_SID" -p local0.err "$pretty_name Success: Operation completed to $fulldest"

	else
		# Not to tape
		cat <<EOF2 > $info_file

The following compressed tarfiles have been created:

${pretty_name}: $date_string

Tarfile 1: File lists (${fulldest}1.Z)
EOF2

		@ counter = 1
		foreach tablespace (`cat tablespaces_${ORACLE_SID}.lst`)
	
			@ counter = $counter + 1
			$ECHO "Tarfile ${counter}: Data files, tablespace $tablespace" >> $info_file
			$ECHO "\t(${fulldest}${counter}.Z)" >> $info_file
		end
	
		@ counter = $counter + 1
		$ECHO "Tarfile ${counter}: Control files (${fulldest}${counter}.Z)" >> $info_file
	
		@ counter = $counter + 1
		$ECHO "Tarfile ${counter}: Parameter files (${fulldest}${counter}.Z)" >> $info_file
	
		cat <<EOF3 >> $info_file

These files should be backed up to tape (or another removable medium)
as soon as possible, labelled appropriately, and the medium should
then be stored in a safe location.
 
EOF3

		cat $info_file

		/usr/ucb/logger -t "IDB_BACKUP-$ORACLE_SID" -p local0.err "$pretty_name Success: Operation completed to ${fulldest}1.Z through ${fulldest}${counter}.Z"
	endif
	
	exit 0
else
	/usr/ucb/logger -t "IDB_BACKUP-$ORACLE_SID" -p local0.err "$pretty_name FAILED: Unexpected backup error"
	exit 22
endif

UNEXPECTED_ERROR:

	$ECHO "\nUnexpected error encountered.\n"
	/usr/ucb/logger -t "IDB_BACKUP-$ORACLE_SID" -p local0.err "$pretty_name FAILED: Unexpected error encountered"
	exit 22
