semio has asked for the wisdom of the Perl Monks concerning the following question:

I am interested in working with logs, PIX in this example, to simulate security devices. To do this, I first obtained a PIX syslog sample.
Dec 7 00:24:47 192.168.0.10 Dec 08 2001 00:30:15: %PIX-3-106011: Deny + inbound (No xlate) tcp src outside:192.168.0.11/3499 dst outside:192 +.168.0.30 Dec 7 15:04:59 192.168.0.10 %PIX-3-106014: Deny inbound icmp src dmz: +10.0.0.2 dst inside:10.0.0.5 (type 8, code 0)
I then wrote a script that would update the date and time stamps in the file according to the format currently used. The solution I came up with is:
#!/usr/bin/perl -w use Text::ParseWords; use strict; my $log = "pixlog"; my $looptime = 300; my $maxsize = 1000; my (@lines, @fields); my ($month, $monthstring, $item, $x); while (1) { my $newlog = `date '+%d%m%Y%H%M%S.fakepix'`; open (LOGFILE, "< $log") || die "Could not open file: $! \n"; @lines = <LOGFILE>; close (LOGFILE); open (NEWLOG, ">$newlog"); monthstring(); foreach $item (@lines) { @fields = quotewords(' ',0,$item); my $time1 = `date '+%H:%M:%S'`; chop $time1; my $time2 = `date '+%H:%M:%S:'`; chop $time2; my $date = `date '+%d'`; chop $date; my $year = `date '+%Y'`; chop $year; if ($fields[7] =~ (m/:\d+\d+:\d+\d+:/)) { $fields[0] = $monthstring; $fields[1] = $date; $fields[2] = $time1; $fields[4] = $monthstring; $fields[5] = $date; $fields[6] = $year; $fields[7] = $time2; } else { $fields[0] = $monthstring; $fields[1] = $date; $fields[2] = $time1; } for ($x=0; $x <= $#fields; $x++) { if ($x eq $#fields) { print NEWLOG "$fields[$x]"; } else { print NEWLOG "$fields[$x]"; print NEWLOG " "; } } } close (NEWLOG); sub monthstring { $month = `date '+%m'`; if ($month =~ /01/) { $monthstring = "Jan"; return $monthstring; } if ($month =~ /02/) { $monthstring = "Feb"; return $monthstring; } if ($month =~ /03/) { $monthstring = "Mar"; return $monthstring; } if ($month =~ /04/) { $monthstring = "Apr"; return $monthstring; } if ($month =~ /05/) { $monthstring = "May"; return $monthstring; } if ($month =~ /06/) { $monthstring = "Jun"; return $monthstring; } if ($month =~ /07/) { $monthstring = "Jul"; return $monthstring; } if ($month =~ /08/) { $monthstring = "Aug"; return $monthstring; } if ($month =~ /09/) { $monthstring = "Sep"; return $monthstring; } if ($month =~ /10/) { $monthstring = "Oct"; return $monthstring; } if ($month =~ /11/) { $monthstring = "Nov"; return $monthstring; } if ($month =~ /12/) { $monthstring = "Dec"; return $monthstring; } } sleep($looptime) }
Although this has a nice result of simulating a flow of log data, I'm not comfortable with the idea of shelling so often. I'm aware of TIMTOWTDI, but I have the feeling TIABWTDI (there is a better way to do it) applies in this case. :) Has anyone worked with updating date/time stamps in a file that doesn't rely on shelling. Of course, other suggestions for improvement are also welcome.
cheers, -semio

Replies are listed 'Best First'.
Re: Modifying date/time stamps
by dws (Chancellor) on Aug 07, 2002 at 02:59 UTC
    I'm not comfortable with the idea of shelling so often. ... I have the feeling TIABWTDI (there is a better way to do it)

    Indeed. That entire sequence of shelling out to get date components can be replaced in one of several ways.   perldoc -f localtime will give you info on one approach.

      and you could replace that huge series of ifs with a @array=qw/jan feb mar.../; $foo=~/(\d+)/;$array[$1]; Basically.

      Also, take a look at strftime in POSIX. It'll even let you use your existing format-strings, since date +foo is just a wrapper around strftime.


      Confession: It does an Immortal Body good.

Re: Modifying date/time stamps
by semio (Friar) on Aug 17, 2002 at 00:23 UTC
    thanks dws, BUU and theorbtwo. That did the trick and strftime enabled me to remove that huge series of ifs as well.

    cheers, -semio

    posting the updated code for comparison purposes.

    #!/usr/bin/perl -w use Text::ParseWords; use POSIX qw(strftime); use strict; my $log = "pixlog"; my $looptime = 300; my $maxsize = 1000; my (@lines, @fields, @devices, @duoutput); my ($devices, $device, $item, $x); while (1) { my $newlog = strftime "%d%m%Y%H%M%S.fakepix.lgz", localtime; open (LOGFILE, "< $log") || die "Could not open file: $! \n"; @lines = <LOGFILE>; close (LOGFILE); open (NEWLOG, ">$newlog"); foreach $item (@lines) { @fields = quotewords(' ',0,$item); my $month = strftime "%b", localtime; my $time1 = strftime "%H:%M:%S", localtime; my $time2 = strftime "%H:%M:%S:", localtime; my $date = strftime "%d", localtime; my $year = strftime "%Y", localtime; if ($fields[7] =~ (m/:\d+\d+:\d+\d+:/)) { $fields[0] = $month; $fields[1] = $date; $fields[2] = $time1; $fields[4] = $month; $fields[5] = $date; $fields[6] = $year; $fields[7] = $time2; } else { $fields[0] = $month; $fields[1] = $date; $fields[2] = $time1; } for ($x=0; $x <= $#fields; $x++) { if ($x eq $#fields) { print NEWLOG "$fields[$x]"; } else { print NEWLOG "$fields[$x]"; print NEWLOG " "; } } } close (NEWLOG); sleep($looptime) }