Perl Script Problems

Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

Threaded View
Hi All, I'm a total newbie to perl but I found a script form the web
that would automate the cloning of Oracle DB's on NT so I thought i'd
give it a go, the problem is whenever i run it i get a badfile error, (
found in the section that backs up Db files - think )which i'm assuming
is becuase my path of some of my db files have a space in them, i'd
appreciate it if anybody can give me a workaround to this


# coldarch -- cold backup for Microsoft
#             G. Patterson, June 2002

# WARNING  ** This script SHUTS DOWN THE DATABASE! ********
#             This is the only warning!

# Set the common parameters (contained in
use File::Basename;
# extract the path from $0
$MyPath = dirname($0);
# This file contains important site definitions
require "$MyPath\";
# This determines how the database will be re-opened
$OPEN_TYPE = 0;         # 0 = Don't open, 1 = oradim, 2 = svrmgrl, 3 =


# Write a log message to the logfile
sub LogMsg{
my @t = localtime(time);
printf LOG "%04d-%02d-%02d %02d:%02d %s\n",


# We have a problem ... cleanup and exit
sub problem{
LogMsg "ERROR: $_[0]";
unlink "$lockfile";
unlink "$stopfile";
# hopefully we can start the database
die "$_[0]\n";

# -------------------------------------------------------------------
# Run the given SQL and spool to temp.LST, because we
# cannot redirect output from version 7 sqlplus in NT
sub run_sql {
# first,  write the given SQL to a temp file
open SQL,">$sqltmp" || die "cannot open $sqltmp";
print SQL "set term off\n";
print SQL "set echo off\n";
print SQL "set trimspool on\n";
print SQL "set pages 0\n";
print SQL "set feedback off\n";
print SQL "set verify off\n";
print SQL "set lines 1024\n";
print SQL "spool $tmpdir\temp\n";
print SQL "$_[0]\n";
print SQL "exit\n";
close SQL || die "$!";
# now run it with the SQLPLUS utility
system "$sqlplus -s $userid/$passwd\@$orasid \@$sqltmp";
# read back the spool file and return the contents in list
open (TMP,"$tmpdir\temp.LST") || problem "opening temp.LST";
my @t = (<TMP>);
close TMP || problem "closing temp.LST";
return( @t);


# Run the given SQL in svrmgrl
sub run_svrmgr {
# construct an SQL file
open SQL,">$sqltmp" || die "cannot open $sqltmp";
print SQL "connect internal/$passwd\n";
print SQL "$_[0]\n";
print SQL "exit\n";
close SQL || die "$!";
# EXEC as a backticks block and return the output in list
my @t = `$svrmgrl \@$sqltmp`;
return( @t);

# get list of redo logs from v_$logfile
sub get_redo_info{
# this should return a list of the redo logs
my @t = run_sql "select member from v_$logfile;";
foreach $x (@t){
# remove any crud from the end of the lines
$x =~ s/\s+$//;
push (@REDOLIST,$x) if (length($x) )


# shutdown the database and get a copy of SQL to create control file
sub shutdb{
my $t; my $f; my $x; my $a;
# run a BACKUP TO TRACE command
my $backup_ctrl = "$coldarc\" . uc($orasid) .
my @t = run_svrmgr "alter system switch logfile;
alter database backup controlfile to trace resetlogs;";
@t = run_svrmgr "shutdown immediate;";
LogMsg $t = `$oradim -shutdown -sid $orasid -usrpwd $passwd
-shuttype inst,srvc -shutmode i`;
# examine the files in USER_DUMP_DEST
opendir (TRACE,$ORAPARM) ||
problem "Cannot open $ORAPARM";
$a = 99;
# we want the most recent trace file ...
while ($t = readdir TRACE){
$x = $ORAPARM . "\" . $t;
next unless ( -f $x);
next unless ( (-M $x ) < $a);
$f = $x;
$a = ( -M $x )
# save the trace file for later (the coldclone procedure)
rename $f,$backup_ctrl || problem "Cannot move $f to

# retrieve parameter values from v$parameter
sub get_oraparm{
# extract the parameters from v$parameter
my @t = run_sql "col name format a40 trunc\ncol value format
a512 trunc
select name,value from v$parameter;";
for my $i ( 0 .. $#t){
$t[$i] =~ s/\s+$//;
# parse them into %ORAPARM (using parameter as a hash
if ( $t[$i] =~ /^(\w+)/){
$ORAPARM = $';
$ORAPARM =~ s/^\s+//;


# Get the list of datafiles to be backed up
sub get_datafiles{
my @t = run_sql "select tablespace_name, file_name, blocks+1
from dba_data_files where status = 'AVAILABLE'
order by tablespace_name, file_name;";
my $j = 0;
for my $i ( 0 .. $#t){
my @s = split ' ',$t[$i];
if (@s == 3){
$DATAFILE[$j] = \@s;
my @b = split /\/,$DATAFILE[$j][1];
$DATAFILE[$j++][3] = $b[$#b];
elsif (@s > 3){
# spit the dummy if filename contains embedded
problem "bad file: $s[1] $s[2]";
problem "no data files available" unless (@DATAFILE > 0);
LogMsg sprintf "$MyName found %d data files to
# Create a header file.
# This is a text file that contains information about the cold archive
# which can be used by scripts that restore from the cold archive.
sub write_header{
my $x;
# gather all the necessary information
# clobber previous backup
unlink glob "$coldarc\*";
open (HDR,">$coldarcheader") || die "Cannot open
# store the information in the header file
print HDR "$MyName started at $start_str
ORACLE_SID: $orasid
PARAM_FILE: $pfile\n";
if ($ORAPARM){
print HDR "    I FILES:\n";
foreach $x(split (/, /,$ORAPARM)){
print HDR "\t$x\n";
print HDR " CTRL FILES:\n";
foreach $x (@CTRLFILES){
print HDR "\t$x\n";


# create SQL for a backup control (backup to trace)
sub backup_control_file{
my $backup_ctrl = "$coldarc\" . uc($orasid) . "_CTRL.FILE";
# clobber any old versions of this file
unlink "$backup_ctrl";
my @t = run_sql "set feedback on
alter database backup controlfile to '$backup_ctrl';";
problem "Cannot backup controlfile"
unless ( grep(/Database altered$/i,@t) );
# use the $zipview command to verify that the backup is successful
# this reads through the contents of the zip archive and checks
# that the sizes match specified system size.
# NB: This may vary from site to site. If you have actually created
# a data file that is larger than the allocated size in the database
# this check should be disabled.
sub verify_backup{
$blksz = $ORAPARM;
for my $i ( 0 .. $#DATAFILE){
my @t = `$zipview $coldarc$DATAFILE[$i][3].zip`;
foreach my $x (@t){
$x =~ s/\s+$//;
if ($x =~ /$DATAFILE[$i][3]$/){
$size = (split ' ',$x)[0];
problem "suspect backup
unless ($size == $DATAFILE[$i][2] *


#make the output from the zipadd more pretty
sub pretty {
my $t = $_[0];
$t =~ s/Deflating     .*%\), done./Deflated/;


# backup the control_file, redo logs, pfiles and ifiles
sub backup_config(){
my $x; my $b;
my $dest = "$coldarc\config.$";
# first copy the pfile to the archive directory
my $t = `copy $pfile $coldarc`;
$t =~ s/\s+$//;
problem "pfile: $t" unless ($t =~ /1 file\(s\) copied/);
# add the control_file to the zip archive
LogMsg pretty $t = `$zipadd $dest $CTRLFILES[0]`;
foreach my $x (@REDOLIST){
LogMsg pretty $t = `$zipadd $dest $x`;
# copy each of the ifiles to the archive directory
foreach $x(split (/, /,$ORAPARM)){
$b = basename( $x);
problem "Duplicate ifile: $b" if ( -f "$coldarc$b");
$t = `copy $x $coldarc`;
$t =~ s/\s+$//;
problem "ifile: $t" unless ($t =~ /1 file\(s\)


# reopen database -- called from problem(), so we must not call
sub opendb{
LogMsg "WARNING: Database is shutdown!" unless $OPEN_TYPE;
LogMsg $t =
`$oradim -startup -sid $orasid -usrpwd $passwd -starttype
if ( $OPEN_TYPE & 1);
run_svrmgr "startup" if ( $OPEN_TYPE & 2);


# Main ... start here:
# which program am I?
$MyName = basename $0,"\.pl";
# sanity check for command line
die "usage: $MyName intrnl_passwd db_name\n" unless (@ARGV == 2);
$userid = "sys";
$passwd = $ARGV[0];
$orasid = $ARGV[1];
# check the environment
# init strings for logfile
@start = localtime(time);
$start_str = sprintf "%04d-%02d-%02d %02d:%02d:%02d",$start[5]+1900,
$logfile = sprintf
$lockfile = "$logdir\coldarch.$orasid.lock";
$stopfile = "$logdir\coldarch.$orasid.stop";
die "$MyName is already running\n" if ((-f $lockfile) && (-M $lockfile
< 1));
# create the lockfile
open (LOCK,">$lockfile") || die "Cannot write to $lockfile";
print LOCK "$MyName started $start_str\n";
close (LOCK) || die "$!";
open(LOG,">>$logfile") || die "error opening $logfile\n";
problem "$ORAPARM does not match $orasid"
unless (uc($ORAPARM) eq uc($orasid));
$coldarc = "$coldarc$ORAPARM";
# setup the header
# shutdown the database, backup control_file, pfile, ifiles
# write information about datafiles to the HEADER
print HDR "\n DATA FILES:\n";
for my $i ( 0 .. $#DATAFILE){
# loop through the datafiles
problem "$MyName Stopped!" if ( -f $stopfile);
LogMsg "copying $DATAFILE[$i][1], $DATAFILE[$i][2] blocks";
print HDR "\t$DATAFILE[$i][1] $DATAFILE[$i][2] blocks\n";
LogMsg pretty $t = `$zipadd $coldarc$DATAFILE[$i][3].zip
LogMsg "$MyName completed normal";
unlink "$lockfile";

Re: Perl Script Problems wrote:

 > Subject: Perl Script Problems

Please put the subject of your post in the Subject of your post.

> Hi All, I'm a total newbie to perl but I found a script form the web

The standard answer is that you should:

   Contact the author for help.
   Learn Perl.
   Hire someone who knows Perl.

The regulars here do not want this newsgroup to become a free "fix this
3rd party script" service.  This newsgroup is for people who want to
discuss or learn Perl.

Note: a quick look at that script indicates that it contains many things
that would be severely criticised if it were posted here for code review.

Site Timeline