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

Hey Perl gurus,

I need your expert advice on how to get the epoch times into a script from multiple syslog files.

Here's what I have so far

#!/usr/bin/perl use Time::Local; $x = &getTime; sub getTime { ($sec,$min,$hour,$mday,$month,$year,$wday, $yday,$isdst)=localtime(tim +e); $epoch = timelocal($sec, $min, $hour, $mday, $month, $year); return $epoch; } @fileTotal = `ls /var/log/syslog*`; #foreach loop opens each log file foreach $file (@fileTotal) { chomp($file); open(FILEREAD, "< $file"); while ($linebuf = <FILEREAD>) { chomp($linebuf); # remove <CR> at the end @data = split(/[ ]+/, $linebuf); if( $data[6] eq "session" && $data[7] eq "opened") { $d1 = index($linebuf, "[", 0); $d2 = index($linebuf, "]", ($d1+1)); $ID = substr($linebuf, ($d1+1), ($d2-$d1-1)); $openTime{$ID} = $epoch; $account{$ID} = $data[10]; } elsif( $data[6] eq "session" && $data[7] eq "closed" +) { # user SSH logoff session $d1 = index($linebuf, "[", 0); $d2 = index($linebuf, "]", ($d1+1)); $ID = substr($linebuf, ($d1+1), ($d2-$d1-1)); $closeTime = $epoch; if( defined $account{$ID}) { $userAccount = $account{$ID}; $duration = $closeTime - $openTime{$ID}; #interval $totalSession{$userAccount}++; $dSession{$userAccount} += $duration; } } } close FILEREAD; + } foreach $x (sort(keys %totalSession)) { $averageSession = $dSession{$x}/$totalSession{$x}; printf "%-10s %10s %10s \t %.2f\n", $x, $totalSession{$x}, $ +dSession{$x}, $averageSession; }

My output gives me continuous 0s though like shown below.

Account Count TotalTime Average 86 0 0.00 root 2 0 0.00 user01 37 0 0.00 user02 4 0 0.00 user03 86 0 0.00 user04 57 0 0.00 user05 945 0 0.00 user06 11 0 0.00 user07 46 0 0.00 user08 17 0 0.00 user09 2 0 0.00 user10 81 0 0.00

Any guidance you guru's can give will be appreciated. Thanks

Code tags added by GrandFather

Replies are listed 'Best First'.
Re: Passing epoch time to function to compare open session time and close session time
by NetWallah (Canon) on Feb 06, 2015 at 05:13 UTC
    Guidance:
    • use <code> tags to make your code legible on this site (see Writeup Formatting Tips).
    • Always "use strict;" and "use warnings;"
    • Use the 3-parameter form of "open", AND do error checking:
      open my $handle, "<" , "My-file-name" or die "Could not open File-name:$!";
    • Dont use "&" for subroutine calls (old style), unless you know what you are doing.
    • "ls" will not return the FULL PATH - just the file names, so you may need to append the path before opening the file.
    We can help you more after you post readable code...

    Update: Typo fixed, Thanks, MidLifeXis.

            "You're only given one little spark of madness. You mustn't lose it."         - Robin Williams

Re: Passing epoch time to function to compare open session time and close session time
by Corion (Patriarch) on Feb 06, 2015 at 07:47 UTC
Re: Passing epoch time to function to compare open session time and close session time
by perloHolic() (Beadle) on Feb 06, 2015 at 12:01 UTC

    Given the above suggestions from NetWallah and Corion, it would also help to include an example of your log files, or at least a few lines of one, to help with understadning what you want to do and what you want to do it with.

    I have made a little start on shaping up your code to compile under warnings and strict, which it now does, but without an example of input, the output of the script is ambigous at best. Update the post to include an effort at addressing NetWallah and Corion's suggestions as well as posting up some input/expected output examples and I (And many others besides) will be more than happy to help, I'm sure.

    All the best.

    EDIT:After further testing with some sample data I mocked up for test case purposes, I believe the problem with getting '0's for everything is that your current calculations are base upon the $epoch variable - Which by my tests show that:

    $openTime{$ID} = $epoch;

    AND

    $closeTime = $epoch;

    produce the same number given that:

    my $duration = $closeTime - $openTime{$ID}; #interval

    which is affectively $epoch minus $epoch = '0'

    This summation is however subject to my current knowledge of things and any corrections are obviously more than welcome, and hopefully this helps a little more with getting you to your solution....

Re: Passing epoch time to function to compare open session time and close session time
by perloHolic() (Beadle) on Feb 06, 2015 at 14:50 UTC

    Here I have rejigged your code somewhat to compile under strict and warnings, however I have tried to leave it as original as possible so you find it familiar and easy to understand.

    #!/usr/bin/perl use warnings; use strict; use Time::Local; my $x = getTime(); my $d1; my $d2; my $ID; my $epoch; my %openTime; my %account; my %totalSession; my %dSession; sub getTime { (my $sec,my $min,my $hour,my $mday,my $month,my $year,my $wday,my + $yday,my $isdst)=localtime(time); $epoch = timelocal($sec, $min, $hour, $mday, $month, $year); return $epoch; } my @fileTotal = `ls /u/user/myarea/test/file*`; #foreach loop opens each log file foreach my $file (@fileTotal) { chomp($file); open(FILEREAD, "< $file"); open FILEREAD, "< $file" or die "Can't open $file for reading - $ +?"; while (my $linebuf = <FILEREAD>) { chomp($linebuf); # remove <CR> at the end my @data = split(/[ ]+/, $linebuf); if( $data[6] eq "session" && $data[7] eq "opened") { $d1 = index($linebuf, "[", 0); $d2 = index($linebuf, "]", ($d1+1)); $ID = substr($linebuf, ($d1+1), ($d2-$d1-1)); $openTime{$ID} = $epoch; $account{$ID} = $data[10]; print "open time= $openTime{$ID}\n"; } elsif( $data[6] eq "session" && $data[7] eq "closed") { # user SSH logoff session $d1 = index($linebuf, "[", 0); $d2 = index($linebuf, "]", ($d1+1)); $ID = substr($linebuf, ($d1+1), ($d2-$d1-1)); my $closeTime = $epoch; print "closetime= $closeTime\n"; if( defined $account{$ID}) { my $userAccount = $account{$ID}; my $duration = $closeTime - $openTime{$ID}; #inter +val $totalSession{$userAccount}++; $dSession{$userAccount} += $duration; } } } close FILEREAD; } foreach $x (sort(keys %totalSession)) { my $averageSession = $dSession{$x}/$totalSession{$x}; printf "%-10s %10s %10s \t %.2f\n",$x,$totalSession{$x},$dSession +{$x}, $averageSession; }

    I used this as an example fo input:

     Jan 31 08:40:19 ubuntu01 sshd[32346]: pam_unix(sshd:session): session opened for user user1 by (uid=1)

     Jan 31 08:45:19 ubuntu01 sshd[32346]: pam_unix(sshd:session): session closed for user user1 by (uid=1)

    That I found in what I believe to be an alternate post of yours.

    As you will be able to see from a simple output debug I put in, epoch is printed on both 'opened' and 'closed' and prints the same number, hence you're '0's issue. I would suggest rethinking your method of determing 'time' and the difference between a 'connection open' time and a 'connection closed' time.

    By no means am I guaranteeing that this code is the best way to do it, it is simply my honest interpretation from your's to 'safe/compilable code' - My usual caveat applies - all edits and suggestions and errors found are more than welcomed as always.

    All the best - your ever faithfull functioning perloHolic