Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Help with script to get backup log status on windows systems

Reply
Thread Tools

Help with script to get backup log status on windows systems

 
 
Matt Williamson
Guest
Posts: n/a
 
      07-19-2006
The purpose of this script is to quickly get a status on all of my nightly
backups. It's working for everything but the .xml backup files. There are
multiple .xml files created each night for the various processes that occur,
the actual backup log is only one of them. I've determined that the .xml
backup log files that I want are all encoded utf16le and the others are
utf8. I only want to read the utf16le .xml files and print the server name
and filename for just the latest of those but I can't figure out the best
way to do it. Also, if you have any suggestions on the script in general,
please feel free to comment. I'm new at this, so any advice from experienced
coders is welcome and appreciated.

use strict;
use warnings;

my @content;
my @header;

my %belogdirs = (
"\\\\Server1" => "\\d\$\\Backup Exec\\data\\bex*.txt",
\\\\Server2 => "\\c\$\\Program Files\\Seagate Software\\Backup
Exec\\Nt\\Data\\bex*.txt",
\\\\Server3 => "\\c\$\\Program Files\\Veritas\\Backup
Exec\\Nt\\Data\\bex*.txt",
\\\\Server4 => "\\c\$\\Program Files\\Veritas\\Backup
Exec\\Nt\\Data\\bex*.txt",
\\\\Server5 => "\\c\$\\Program Files\\Veritas\\Backup
Exec\\Nt\\Data\\bex*.txt",
\\\\Server6 => "\\c\$\\Program Files\\Veritas\\Backup
Exec\\Nt\\Data\\bex*.xml"
);

open FILE, ">C:\\Backup Tape Log.txt";
foreach my $server (keys %belogdirs) {
my $fullpath = $server.$belogdirs{$server};
my @files = `dir "$fullpath" /OD /B`;
foreach my $file (reverse @files) {
$fullpath =~ s/bex\*\.xml|bex\*\.txt/$file/i;
chomp $fullpath;
open F, $fullpath or die "can't open $file: $!\n";
read F, my $buffer, 2;
@header = unpack "h*", $buffer;
close F;

if ($header[0] =~ /ffef/i) { #handle the utf16 .xml files
open F, "<:encoding(utf16le)", $fullpath or
die "can't open $file: $!\n";
@content = <F>;
close F;
}
elsif ($header[0] =~ /efff/i) { # just in case?
open F, "<:encoding(utf16be)", $fullpath or
die "can't open $file: $!\n";
@content = <F>;
close F;
}
else { # handle the .txt files
open F, $fullpath or
die "can't open $file: $!\n";
@content = <F>;
close F;
}

# $server =~ s/\\\\/Server: /;
# print FILE $server, "\n";
# print FILE "Log File: ",$fullpath,"\n";

foreach my $line (@content){
if ($line =~ /(job (?:started|ended|completion status)):\s*(.*?)\s*$/i) {
my ($job_type, $status) = ($1, $2);
print FILE "$job_type: $status\n";
}
}
print FILE "\n";
last;
}
}

close FILE;
exec("notepad C:\\Backup Tape Log.txt");


TIA

Matt


 
Reply With Quote
 
 
 
 
Matt Williamson
Guest
Posts: n/a
 
      07-19-2006
So, getting the first 2 bytes of the file, converting them to hex and
checking the string representation of the hex characters isn't the right way
to do it? That part seems to work fine. What is a better way?
It took me 4 hours to come up with that <g>

Matt

"A. Sinan Unur" <(E-Mail Removed)> wrote in message
news:Xns98057A8FCC814asu1cornelledu@127.0.0.1...
> "Matt Williamson" <(E-Mail Removed)> wrote in
> news:e9lkp8$9gt$(E-Mail Removed):
>
>> if ($header[0] =~ /ffef/i) { #handle the utf16 .xml files

>
> I can't comment on the rest of your post, but here you are looking for a
> sequence of characters 'f', 'f', 'e', 'f' anywhere in the string. Those
> characters have nothing to do with the BOM.
>
> http://www.unicode.org/faq/utf_bom.html#BOM
>
> Sinan
>
> --
> A. Sinan Unur <(E-Mail Removed)>
> (remove .invalid and reverse each component for email address)
>
> comp.lang.perl.misc guidelines on the WWW:
> http://augustmail.com/~tadmc/clpmisc...uidelines.html
>



 
Reply With Quote
 
 
 
 
Ben Morrow
Guest
Posts: n/a
 
      07-19-2006

Quoth "Matt Williamson" <(E-Mail Removed)>:
> The purpose of this script is to quickly get a status on all of my nightly
> backups. It's working for everything but the .xml backup files. There are
> multiple .xml files created each night for the various processes that occur,
> the actual backup log is only one of them. I've determined that the .xml
> backup log files that I want are all encoded utf16le and the others are
> utf8. I only want to read the utf16le .xml files and print the server name
> and filename for just the latest of those but I can't figure out the best
> way to do it. Also, if you have any suggestions on the script in general,
> please feel free to comment. I'm new at this, so any advice from experienced
> coders is welcome and appreciated.
>
> use strict;
> use warnings;


Good .

> my @content;


This variable is not needed at this scope. You should declare it inside
the first loop, as that's where you use it.

> my @header;


This variable is only needed per-file, so you should declare it
per-file. But see below for why I don't think you need it at all...

> my %belogdirs = (
> "\\\\Server1" => "\\d\$\\Backup Exec\\data\\bex*.txt",
> \\\\Server2 => "\\c\$\\Program Files\\Seagate Software\\Backup
> Exec\\Nt\\Data\\bex*.txt",
> \\\\Server3 => "\\c\$\\Program Files\\Veritas\\Backup
> Exec\\Nt\\Data\\bex*.txt",
> \\\\Server4 => "\\c\$\\Program Files\\Veritas\\Backup
> Exec\\Nt\\Data\\bex*.txt",
> \\\\Server5 => "\\c\$\\Program Files\\Veritas\\Backup
> Exec\\Nt\\Data\\bex*.txt",
> \\\\Server6 => "\\c\$\\Program Files\\Veritas\\Backup
> Exec\\Nt\\Data\\bex*.xml"
> );


This would be easier with forward slashes and single quotes:

'//Server1' => '/d$/Backup Exec/data/bex*.txt',

> open FILE, ">C:\\Backup Tape Log.txt";


It is generally safer to use lexical FHs and three-arg open, and you
should *always* check the return value:

open my $FILE, '>', 'c:/Backup Tape Log.txt'
or die "can't open 'c:/Backup Tape Log.txt': $!";

> foreach my $server (keys %belogdirs) {
> my $fullpath = $server.$belogdirs{$server};
> my @files = `dir "$fullpath" /OD /B`;


OK, now you'll hit the only snag of using forward slashes: cmd.exe and
most native NT commands don't like it . You can either convert, with
either a simple s!/!\\!g or with File::Spec::Functions::canonpath, or
(probably better) you can use (I guess) glob to do the globbing in Perl.
(I'm not entirely sure glob will do what you want, as I don't know what
/OD /B means to dir, but you can certainly emulate it with either glob
or File::Find.)

> foreach my $file (reverse @files) {
> $fullpath =~ s/bex\*\.xml|bex\*\.txt/$file/i;
> chomp $fullpath;


Ick. This will work, I guess, but it's pretty nasty. I think at this
point I'd do the whole thing a little differently, starting with a
datastructure more like

my %belogdirs = (
Server1 => {
path => 'd$/Backup Exec/data',
extn => 'txt',
},
...
Server6 => {
dir => 'c$/Program Files/Veritas/Backup Exec/Nt/Data',
extn => 'xml',
},
);

for (keys %belogdirs) {
my $glob = "//$_/$belogdirs{$_}{path}/bex*.$belogdirs{$_}{extn}";

Actually, although I normally hate it (in Perl), that would probably be
clearer as a sprintf:

my $glob = sprintf '//%s/%s/bex*.%s' =>
$_, $belogdirs{$_}{path}, $belogdirs{$_}{extn};

for (reverse glob $glob) {
open my $F, '<', $_ or die ...;

Note that glob returns full paths, rather than just a list of names.

> open F, $fullpath or die "can't open $file: $!\n";
> read F, my $buffer, 2;
> @header = unpack "h*", $buffer;


Why are you using an array when you only have one return value?

> close F;
>
> if ($header[0] =~ /ffef/i) { #handle the utf16 .xml files


You're not doing a pattern match here, you are checking for equality.
But you don't need to: if you can be sure your XML files will always
have a BOM, you can simply open the file :encoding(utf16). This will
throw an exception on the first read if there isn't a BOM. So,
continuing from the above:

for my $file (reverse glob $glob) {
my $mode;
$belogdirs{$_}{extn} eq 'xml'
and $mode = ':encoding(utf16)';

# I don't really like file extensions, but if you've got
# 'em you might as well use 'em...

open my $F, "<$enc", $file
or die "can't open '$file': $!";

eval {
@content = <$F>;
1;
} or next;
}

This will skip onto the next file if the read throws an exception.

> open F, "<:encoding(utf16le)", $fullpath or
> die "can't open $file: $!\n";
> @content = <F>;
> close F;
> }
> elsif ($header[0] =~ /efff/i) { # just in case?
> open F, "<:encoding(utf16be)", $fullpath or
> die "can't open $file: $!\n";
> @content = <F>;
> close F;
> }
> else { # handle the .txt files
> open F, $fullpath or
> die "can't open $file: $!\n";
> @content = <F>;
> close F;
> }
>
> # $server =~ s/\\\\/Server: /;
> # print FILE $server, "\n";
> # print FILE "Log File: ",$fullpath,"\n";
>
> foreach my $line (@content){
> if ($line =~ /(job (?:started|ended|completion status)):\s*(.*?)\s*$/i) {
> my ($job_type, $status) = ($1, $2);
> print FILE "$job_type: $status\n";


If you set $\ = "\n" then Perl'll print them for you.

> }
> }


It really helps a lot to keep you indentation sane.

> print FILE "\n";
> last;


I don't understand what this is here for?

> }
> }
>
> close FILE;
> exec("notepad C:\\Backup Tape Log.txt");


Does that work? It didn't ought to: the filename has spaces in it. I
would recommend using exec LIST so Perl does the nasty cmd.exe quoting
for you, even though it's not strictly as safe is it is on a real
platform:

exec notepad => 'c:\\Backup Tape Log.txt';

I would also put this filename in a variable. Never write the same thing
twice.

Ben

--
Outside of a dog, a book is a man's best friend.
Inside of a dog, it's too dark to read.
http://www.velocityreviews.com/forums/(E-Mail Removed) Groucho Marx
 
Reply With Quote
 
anno4000@radom.zrz.tu-berlin.de
Guest
Posts: n/a
 
      07-20-2006
A. Sinan Unur <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> "Matt Williamson" <(E-Mail Removed)> wrote in
> news:e9lohn$jip$(E-Mail Removed):
>
> > "A. Sinan Unur" <(E-Mail Removed)> wrote in message
> > news:Xns98057A8FCC814asu1cornelledu@127.0.0.1...
> >> "Matt Williamson" <(E-Mail Removed)> wrote in
> >> news:e9lkp8$9gt$(E-Mail Removed):
> >>
> >>> if ($header[0] =~ /ffef/i) { #handle the utf16 .xml files
> >>
> >> I can't comment on the rest of your post, but here you are looking
> >> for a sequence of characters 'f', 'f', 'e', 'f' anywhere in the
> >> string. Those characters have nothing to do with the BOM.
> >>
> >> http://www.unicode.org/faq/utf_bom.html#BOM

>
> > So, getting the first 2 bytes of the file, converting them to hex and
> > checking the string representation of the hex characters isn't the
> > right way to do it? That part seems to work fine. What is a better
> > way? It took me 4 hours to come up with that <g>

>
> I did not realize that was what you were doing.


It is a rather roundabout way of checking the first two bytes of
a string.

read F, my $buffer, 2;
@header = unpack "h*", $buffer;
if ($header[0] =~ /ffef/i) { #handle the utf16 .xml files

Instead, define a string constant that contains the relevant two
bytes and compare (untested):

use constant BOM => "\xFF\xEF";

read F, my $buffer, 2;
if ( $buffer eq BOM ) { # handle the utf16 .xml files

Anno
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Maybe C is the perfect language for really good systems programmers, but unfortunately not-so-good systems and applications programmers are using it and they shouldn’t be. Casey Hawthorne C Programming 18 11-06-2009 05:05 AM
Voip PBX,Private Phone Systems,PBX Telephone Systems, Business Phone Systems broadbandera@gmail.com UK VOIP 9 07-24-2006 03:44 PM
Re: Voip PBX,Private Phone Systems,PBX Telephone Systems, Bu George Orwell UK VOIP 0 07-23-2006 05:35 PM
Any computer systems match good home systems? Richard DVD Video 7 08-24-2004 02:54 AM
java as a systems administration/systems programming language? Mike Java 2 06-17-2004 03:33 PM



Advertisments