Forum OpenACS Q&A: Response to Oracle hotbackup scripts?

Collapse
Posted by Andrew Piskorski on
Ok, here's my export script. Note that it's a little more complicated than necessary in order to be useful from the command line as well as from crontab. I just run it from crontab every night with the default values, but you'll probably want to either change the defaults, or add some command-line switches in your crontab to override the defaults.

Just run "ora-export.sh -h" to get help on the command line options.

#!/bin/sh
#
# ora-export.sh
# $Header: /home/cvsroot/unix/usr/local/adm/bin/ora-export.sh,v 1.3 2002/06/17 17:24:02 andy Exp $
#
# by atp@piskorski.com, 2002/05/29
#
# Script to do an Oracle export using a named pipe, gzip, and split,
# as described in _Expert One-on-One Oracle_ by Thomas Kyte,
# pg. 327-328, "Export to an OS Pipe".  This lets us avoid exp's
# possible 2 gig file size limit, use less work space on disk by not
# first writing out an un-compressed export file, etc.


# We assume that /etc/profile sets and exports ORACLE_SID,
# ORACLE_HOME, etc.:

. /etc/profile


# Various defult settings, most of which may be overridden on the
# command line:

# This PASSWORD_FILE must be a Bourne shell script which these
# variables like this:
#   ORA_USERNAME="username"
#   ORA_PASSWORD="password"

# TODO: Putting the password in a file like this keeps us from having
# to hard-code it into multiple script files, but the password STILL
# DOES show up in ps -ef output - not good.

PASSWORD_FILE="/usr/local/adm/bin/ora-system-password.sh"
PUT_IN_DIR="/web/oracle-backups"
MAX_SIZE=600
FULL_P=1
LOG_DATE_FORMAT='+%a %Y-%m-%d %H:%M:%S %Z'

# TODO: For use on multiple machines, may want to move the above
# default settings into a separate configuration file, and source that
# file here.  Perhaps just use the same $PASSWORD_FILE.


CMDNAME=`basename $0`

USAGE="Do nightly Oracle export, using exp, gzip, and split. 

Usage:  ${CMDNAME} [-p FILE] [-d DIRECTORY] [-m SIZE] [-f {0|1}] 

        [-o USER] [-r LOG_FILE] 

Where: 

  -p  : Username/password file to source to set the ORA_USERNAME 

        and ORA_PASSWORD variables. 

        Default:  $PASSWORD_FILE 

  -d  : Directory where we will put the Oracle export file. 

        Default:  $PUT_IN_DIR 

  -m  : Max size of each dump file chunk, in megabytes. 

        Default:  $MAX_SIZE 

  -f  : Full instance export, 1 for yes, 0 for no. 

        Default:  $FULL_P 

  -o  : Oracle schema owner user name to export.  Only needed if -f is no. 

  -r  : Redirect stdout and stdin to file.  Set to empty string to 

        turn off default redirection to the log file. 
"

password_file=$PASSWORD_FILE
put_in_dir=$PUT_IN_DIR
max_size=$MAX_SIZE
full_p=$FULL_P
owner=""
redirect_p=0

direct_p=1
compress_p=1
consistent_p=1

while getopts hp:d:m:f:o:r: OPT
do
  case $OPT in
    h)  
        echo "$USAGE"
        exit
        ;;
    p)  password_file=$OPTARG
        ;;
    d)  put_in_dir=$OPTARG
        ;;
    m)  max_size=$OPTARG
        ;;
    f)  full_p=$OPTARG
        ;;
    o)  owner=$OPTARG
        ;;
    r)  STDOUT=$OPTARG
        STDERR=$OPTARG
        redirect_p=1
        ;;
    ?)
        echo 1>&2
        echo "ERROR:  One or more bad command line options." 1>&2
        echo 1>&2
        echo "$USAGE" 1>&2
        exit 1
        ;;
  esac
done
shift `expr $OPTIND - 1`

ORA_USERNAME=""
ORA_PASSWORD=""
. $password_file

weekday=`date "+%a"`

# TODO: We only have one Oracle instance on this machine.  If we add
# another, we'll need to change things to optionally take the
# ORACLE_SID as a command line option, or something like that:
# --atp@piskorski.com, 2002/05/29 11:03 EDT

if [ "$full_p" -eq 1 ]
then
  full_opt="full=y"
  owner_opt=""
  dump_file="${ORACLE_SID}-${ORA_USERNAME}-full-${weekday}.dmp.gz"
  log_file="${ORACLE_SID}-${ORA_USERNAME}-full-${weekday}.log"
else
  full_opt="full=n"
  if [ "$owner" = "" ]
  then
    owner="$ORA_USERNAME"
  fi
  owner_opt="owner=$owner"
  dump_file="${ORACLE_SID}-${owner}-${weekday}.dmp.gz"
  log_file="${ORACLE_SID}-${owner}-${weekday}.log"
fi


# Redirect stdout and stderr to where?  Settings STDOUT and STDERR to
# empty string will cause no redirection to occur at all:

if [ "$redirect_p" -ne 1 ]
then
  STDOUT=$log_file
  STDERR=$log_file
fi

# Truncate the old previous log file:
cat -s '' > $log_file

if [ "$ORA_USERNAME" = "" ]
then 
  echo "Error: ORA_USERNAME not set." 1>&2  1>>$STDOUT 2>>$STDERR
  exit 1
fi

if [ "$ORA_PASSWORD" = "" ]
then 
  echo "Error: ORA_PASSWORD not set." 1>&2  1>>$STDOUT 2>>$STDERR
  exit 1
fi


if [ "$direct_p" -eq 1 ]
then
  direct_opt="direct=y"
else
  direct_opt="direct=n"
fi

if [ "$compress_p" -eq 1 ]
then
  compress_opt="compress=y"
else
  compress_opt="compress=n"
fi

if [ "$consistent_p" -eq 1 ]
then
  consistent_opt="consistent=y"
else
  consistent_opt="consistent=n"
fi

# The process id of this running script:
pid=$$

ora_exp_maxsize="${max_size}m"
pipe="/tmp/${dump_file}-${pid}"
cd $put_in_dir

if [ -p $pipe ]
then
  # We've included the PID in the pipe name, so this is pretty
  # unlikely:

  echo "WARNING: Named pipe $pipe already existed!" 1>&2  1>>$STDOUT 2>>$STDERR
  echo   `ls -l $pipe`  1>&2  1>>$STDOUT 2>>$STDERR
fi


rm -f $pipe
mknod $pipe p

if [ $? -ne 0 ]
then
  echo "ERROR: Failed to create named pipe: $pipe" 1>&2  1>>$STDOUT 2>>$STDERR
  exit 1
fi

echo "$CMDNAME export STARTING:  `date "$LOG_DATE_FORMAT"`"  1>>$STDOUT 2>>$STDERR

# Note: If this week's export is smaller than last week's, then simply
# overwriting the files might leave one extra split file from LAST
# week, which would mess things up when we re-combine the split files
# in order to do an import.  So go and delete the old dump files
# first, rather than simply overwriting them:

rm -f ${dump_file}.*

gzip < $pipe | split -b $ora_exp_maxsize - ${dump_file}. &
exp $ORA_USERNAME/$ORA_PASSWORD file=$pipe $full_opt $owner_opt $consistent_opt $direct_opt $compress_opt  1>>$STDOUT 2>>$STDERR

echo "$CMDNAME export DONE:  `date "$LOG_DATE_FORMAT"`"  1>>$STDOUT 2>>$STDERR

# To import the dump files we just created, something like this will work:
#
#   cat `ls -1 ${dump_file}.* | sort` | gunzip > $pipe &
#   imp $ORA_USERNAME/$ORA_PASSWORD file=$pipe show=y

rm -f $pipe