| |||||||||
![]() |
|
|
«
Previous Thread
|
Next Thread
»
|
Thread Tools | Search this Thread | Rate Thread | Display Modes |
|
#1
|
||||
|
||||
|
Backup with Perl
#! /usr/bin/perl
# This script is public domain # Comments or suggestions to djl@dplace.com =head1 NAME backup - System backup script =cut use Getopt::Long; use File::Copy; use IO::Handle; if ( $0 !~ /tmp/ ) { # Put myself in /tmp and rexec so that /usr/local can be unmounted. copy( $0, "/tmp/backup" ); exec "perl /tmp/backup @ARGV"; } @Tapes = glob("/dev/rmt/?"); # Set defaults $Tape = $Tapes[0]; $Auto = 0; $Verify = ''; $Level = 0; $Force = 0; $RunMode = `who -r | awk '{print \$3}'`; chomp($RunMode); $Log = "/var/log/dump_out"; $Compress = 1; $Rewind = 0; $Tnum = 0; $Verbose = 0; $rewind = 0; =head1 SYNOPSIS backup [-Auto] [-Force] [-Help] [-[No]Compress] [-Rewind] [-Verify] [-Verbose] [-Tape N] [-Rtape <fullpath>] [-Level 1-9] [mount_point ...] -Auto puts all filesystems on one (possibly continued) tape -Force dumps even if the unmount fails -Level 1 to 9 does an incremental dump -Tape specifies the tape device number, default is 0 Specify \"A\" to auto-select drive 0 or 1 on different days -Rtape specifies the the full pathname of the tape device e.g. host:/dev/rmt/0 -Compress ask the drive to compress the data -Rewind rewinds, not ejects, the tape after a dump -Verify compares the tape after a dump (should be single user) -Verbose prints more output -Help prints this message =cut $USAGE = "Usage: backup [-Auto] [-Force] [-[No]Compress] [-Rewind] [-Verify] [-Verbose] [-Tape N] [-Rtape <fullpath> [-Level 1-9] [-Help] [mount_point ...] -Auto puts all filesystems on one (possibly continued) tape -Force dumps even if the unmount fails -Level 1 to 9 does an incremental dump -Tape specifies the tape device number, default is $Tnum Specify \"A\" to auto-select drive 0 or 1 on different days -Rtape specifies the the full pathname of the tape device e.g. host:/dev/rmt/0 -Compress ask the drive to compress the data -Rewind rewinds, not ejects, the tape after a dump -Verify compares the tape after a dump (should be single user) -Verbose prints more output -Help prints this message "; =head1 DESCRIPTION This is a wrapper script around B<ufsdump>(1m) to do complete or incremental system backups to tape. If I<mountpoint> is not specified, /etc/vfstab is read to determine what filesystems exist on the system, and all filesystems will be dumped. Filesystems are unmounted, if possible, before dumping and remounted afterward. Dump output is logged to /var/log/dump_out for a level 0 dump, or /var/log/dump_out-levelN for an incremental dump in addition to being written to I<stdout>. =cut =head1 EXAMPLES Incremental dumps are normally run from crontab: #30 5 * * * /usr/local/etc/backup -t A -a -f -r -l 5 >/dev/null 2>&1 30 5 * * 0,2,4,6 /usr/local/etc/backup -t 0 -a -f -r -l 5 30 5 * * 1,3,5 /usr/local/etc/backup -device ws02:/dev/rmt/0 -a -f -r -l 5 =cut sub Usage { print $USAGE; unlink "/tmp/backup"; exit 0; } GetOptions( "Auto" => \$Auto, "Compress!" => \$Compress, "Force" => \$Force, "Level=i" => \$Level, "Tape=s" => \$Tnum, "Rtape=s" => \$Tape, "Rewind" => \$Rewind, "Verify" => \$Verify, "Verbose" => \$Verbose, "Help" => \&Usage ) or &Usage; if( $Auto ) { $Rewind = 1; } if( $Level ) { $Rewind = 1; $Log = "$Log-level$Level"; } if( $Tnum ne 0 ) { if( $Tnum eq 'A' ) { $Tape = $Tapes[(localtime)[7] % scalar(@Tapes)]; } else { $Tape = "/dev/rmt/$Tnum"; } } if( $Tape !~ /:/ and not grep(/^$Tape$/, @Tapes) ) { print "Tape device $Tape doesn't seem to exist\n"; exit 1; } if( $Verify ) { $Verify = 'v' } if( @ARGV ) { @Disks = @ARGV; if( @ARGV > 1 ) { $Rewind = 1; } } else { @Disks = (); } if( $Compress == 1 ) { $Compress = 'c'; } else { $Compress = ''; } if( $Rewind == 1 ) { $Rewind = 'n'; } else { $Rewind = ''; } # Check effective user id if( $> != 0 ) { print "Only root can do backups!\n"; unlink "/tmp/backup"; exit 1; } $SIG{INT} = \&cleanup; open(LOG, ">>$Log") || die "Unable to append to $Log\n"; LOG->autoflush(1); system( "date >>$Log" ); $first = 1; $file = 0; # Main Loop # Read /etc/vfstab and dump each selected filesystem open(VFSTAB, "< /etc/vfstab") || die "Unable to read /etc/vfstab"; while( <VFSTAB> ) { chomp; # Skip comments next if /^#/; ($DEV, $RDEV, $FS, $TYPE, $PASS, $BOOT, $OPTIONS) = split; # Ignore non-ufs filesystems next unless $TYPE eq "ufs"; # /oldroot is a special case next if $FS eq "/oldroot" or $FS eq "/unused"; ($disk = $DEV) = s|.*/(.*)..$|$1|; ($ctrl = $disk) =~ s/c(\d*)t.*/$1/; ($tgt = $disk) =~ s/.*t(\d*)d.*/$1/; $indx = $ctrl * 16 + $tgt; if( @Disks != 0 ) { # Dump listed FS only unless( grep /^$FS$/, @Disks ) { next; } $ans = 'y'; } elsif ( $Auto == 1 or ( $Level != 0 and $RunMode eq 'S' ) ) { $ans = 'y'; } else { print "Dump $FS ? "; chomp($ans = scalar(<STDIN>)); } if( $ans eq 'q' ) { unlink "/tmp/backup"; exit 0; } if( $ans eq 'y' ) { if( ($FS ne "/" and $FS ne "/usr" and $FS ne "/var") and -d "$FS/lost+found" ) { $rc = system( "umount $FS 2>&1" ); if( $rc == 0 ) { print "Unmounted $FS\n" if $Verbose; $remount = 1; } elsif( $Force == 1 ) { print "Unable to unmount $FS\n"; print LOG "Unable to unmount $FS\n"; $remount = 0; } else { print "Unable to unmount $FS, dump aborted\n"; print LOG "Unable to unmount $FS, dump aborted\n"; $remount = 0; next; } } print "Dumping $FS on file $file on $Tape$Compress$Rewind\n"; print LOG "Dumping $FS on file $file on $Tape$Compress$Rewind\n"; print "Running \"ufsdump ${Level}cu${Verify}f ${Tape}${Compress}${Rewind} $RDEV\"\n" if $Verbose; if ( open(T, ">/dev/tty") ) { close (T); $have_tty = 1; $rc = system( "ufsdump ${Level}cu${Verify}f ${Tape}${Compress}${Rewind} $RDEV </dev/tty 2>&1 | tee -a $Log" ); } else { $have_tty = 0; $rc = system( "ufsdump ${Level}cu${Verify}f ${Tape}${Compress}${Rewind} $RDEV 2>&1 | tee -a $Log" ); } if( $rc != 0 ) { $rc &= 0xffff; printf "ufsdump returned $rc(0x%04X)\n", $rc; printf LOG "ufsdump returned $rc(0x%04X)\n", $rc; if( $have_tty ) { print "Do you wish to continue? "; chomp($ans = scalar(<STDIN>)); } else { $ans = 'n'; } if( $ans ne 'y' ) { print "Backup aborted\n"; print LOG "Backup aborted\n"; &cleanup(); } } if( $remount == 1 ) { system( "mount $FS" ); } ++$file; $first = 0; } } close(VFSTAB); system( "date >>$Log" ); print LOG "\n"; close(LOG); print "Dump log is in $Log\n"; if( $Rewind eq 'n' ) { print "Rewinding $Tape\n" if $Verbose; if( $Tape =~ /:/ ) { # Remote device ($Host = $Tape) =~ s/:.*//; $Tape =~ s/.*://; system( "rsh $Host mt -f $Tape rewind" ); } else { system( "mt -f $Tape rewind" ); } } else { print "Unloading $Tape\n" if $Verbose; if( $Tape =~ /:/ ) { # Remote device ($Host = $Tape) =~ s/:.*//; $Tape =~ s/.*://; system( "rsh $Host mt -f $Tape rewofl" ); } else { system( "mt -f $Tape rewofl" ); } } unlink "/tmp/backup"; exit 0; sub cleanup { system( "pkill ufsdump" ); if( $FS and not -d "$FS/lost+found" ) { system( "mount $FS" ); } if( $Rewind eq 'n' ) { if( $Tape =~ /:/ ) { # Remote device ($Host = $Tape) =~ s/:.*//; $Tape =~ s/.*://; system( "rsh $Host mt -f $Tape rewind" ); } else { system( "mt -f $Tape rewind" ); } } unlink "/tmp/backup"; exit 1; } |
![]() |
| Viewing: ASP Free Forums > Programming > Code Bank > Backup with Perl |
| Thread Tools | Search this Thread |
| Display Modes | Rate This Thread |
|
|
|
|