Re: automate ontape -r
Posted in 2005
We created a perl script to do an automated restore from an archive that
is done to a filesystem and will handle n number of files (tapes). It
is just a restore from a level 0 archive and there is no logic in it to
roll forward any logical logs. You could probably modify it to handle
restoring from tape.
This script has only been run under versions 9.21 and 9.3 on Solaris
2.6. It would probably work with previous versions, but we haven't
tested it under them. Use this at your own risk.
#!/local/bin/perl
#!/local/bin/perl -d
#########################################################################
###
### Script Name - db_ontape_rest.pl
###
### SYNOPSIS:
###
### db_ontape_rest.pl BUPDEVICE
### Arguments:
### BUPDEVICE Backup Device Name - Informix's TAPEDEV
### most likely lvl0.out
###
### DESCRIPTION:
###
### Perl program to run an Informix archive restore using the
### ontape command without human intervention. The program is
### intended to restore archives from disk and will
### automatically switch tapes when requested. This will not
### do a logical restore, it answers 'N' to restoring logical
### logs.
###
#########################################################################
## Program Arguments Passed
$bckupdev = @ARGV[0];
## Global vars definitions
$P = $0;
$cur_tapeno = 0;
$prv_tapeno = 0;
$nxt_tapeno = 0;
$| = 1;
$restore_cmd = "ontape -r";
$errstr = "?";
$errno = 9999;
$cont_cnt = 0;
$sleep_time = 10;
$pid = $$;
chop($basenm = `basename $bckupdev .out`);
chop($arc_dir = `dirname $bckupdev`);
chop($first_file = `ls $arc_dir/$basenm.*.1`);
@file_parms = split('\\.',$first_file);
$arc_llog = @file_parms[2];
$arc_date = @file_parms[3];
$tmp_file = "/dbbackup/tmp/db_ontape_r_$pid.out";
$work_file = "/dbbackup/tmp/db_ontape_r_$pid.tmp";
$pipe_file = "/dbbackup/tmp/db_ontape_r_$pid.pipe";
## Subs
##########################################################
# switch_tape
##########################################################
sub switch_tape
{
$prv_tapeno=$cur_tapeno-1;
$nxt_tapeno=$cur_tapeno+1;
$cur_tapevol = "$arc_dir/$basenm.$arc_llog.$arc_date.$cur_tapeno";
$nxt_tapevol = "$arc_dir/$basenm.$arc_llog.$arc_date.$nxt_tapeno";
$is_nxt_tape = system("ls $nxt_tapevol>/dev/null 2>&1");
if ($cur_tapeno > 0)
{
# move prev tape out of the backup device
$rc = system("mv $bckupdev $cur_tapevol");
if ($rc != 0)
{
$errstr = "File Move $bckupdev -> $cur_tapevol";
$errno = 3;
&error("Error during file move: $bckupdev -> $cur_tapevol - exiting");
}
## Add completed tape volume to the tape list array
push(@tape_list,$cur_tapevol);
}
if ($is_nxt_tape == 0)
{
## Switch Tapes
$rc = system("mv $nxt_tapevol $bckupdev");
if ($rc != 0)
{
$errstr = "File Move $nxt_tapevol -> $bckupdev";
$errno = 3;
&error("Error during file move: $nxt_tapevol -> $bckupdev - exiting");
}
## set permissions
system("chmod 0664 $bckupdev");
$cur_tapeno=$nxt_tapeno;
$nxt_tapeno++;
}
}
##########################################################
# error
##########################################################
sub error
{
$msg = @_[0];
print "$P -- Fatal Error: $msg\\n";
if ($cur_tapeno > 0) { &switch_tape(); }
&display_log();
&cleanup();
exit 1
}
##########################################################
# Cleanup
##########################################################
sub cleanup
{
# Remove work files
system("rm /dbbackup/tmp/db_ontape_r_$pid.*");
}
##########################################################
# Display Logfile
##########################################################
sub display_log
{
print "$P | ontape output:\\n";
print "** Log Start
******************************************************\\n";
system("cat $tmp_file");
print "** Log End
********************************************************\\n";
}
###########################################################
# Main
###########################################################
## Create ontape input pipe
print "$P | Creating new $pipe_file\\n";
if (system("mkfifo $pipe_file") != 0)
{
&error("Error: Can't create $pipe_file - exiting");
}
## Create ontape ouptut file
print "$P | Creating new $tmp_file\\n";
if (system("touch $tmp_file") != 0)
{
&error("Error: Can't create $tmp_file - exiting");
}
## Start backup process in background
print "$P | Starting background $restore_cmd\\n";
if (system("$restore_cmd < $pipe_file > $tmp_file &") != 0)
{
system("echo $?");
&error("Error: Can't fire up $restore_cmd - exiting");
}
## Open pipe
print "$P | Opening np_in named pipe\\n";
open(NP_IN, ">$pipe_file") || die "can't open np - $!";
## Read from command output pipe
$stop = 0;
print "$P | Entering main processing loop - sleep time $sleep_time
seconds\\n";
READ:
while($stop==0)
{
## read contents of out file to save the last record
open(NP_OUT, "tail -1 $tmp_file |") || die "can't $tmp_file np - $!";
## Just in case read fails
$rec = "crudcrudcrudcrudcrud";
## while (read(NP_OUT,$_,150))
while (<NP_OUT>)
{
if (
/Interrupt/i
|| /tape is still mounted/i
|| /cannot open/i
|| /failed/i
|| /Terminated/i
|| /Abort/i
|| /ERROR/i
|| /incompatible/i
) { &error("ontape failure"); }
$rec = $_;
}
close(NP_OUT);
## get last output line
$this_msghdr = $rec;
## Check to see if this message has been previously seen
$found_it = 0;
foreach $this_hist (@hist_msghdr)
{
if ($this_hist eq $this_msghdr )
{
$found_it = 1;
}
}
if (
$this_msghdr eq $last_msghdr ||
$rec eq "crudcrudcrudcrudcrud" ||
$found_it == 1
)
{
system("sleep $sleep_time");
print ".";
$sleep_count++;
next READ;
}
push(@hist_msghdr,$this_msghdr);
$sleep_tot = ($sleep_count * $sleep_time) / 60;
$grand_sleep_tot += $sleep_tot;
print "\\n\\n$P | Waking up from sleeping $sleep_tot minutes\\n";
print "\\n\\n$P | Encountered next message: ", $this_msghdr, "\\n";
$sleep_count = 0;
## Mount the next tape
if ( $rec =~ /Restore a