PMG76
asked on
unix logon summary
I need some help making a program that prints a summary to the screen using the "last" command in Unix. I need to take the account, terminal, hostname, date (in HH:MM format), login, logout, and duration fields and output the following information formatted like this: ACCOUNT = LOGINS = TIME. I'm not sure really how to begin. I would appreciate some help understanding how to do this.
ASKER
We have not covered hashes yet. I need to do it without hash references.
You could use two arrays where the login is the array element that will count the number of logins.
and the other array with the login as an element reference is the duration counter.
The other option is to run the last command as many times as there are individual users
I.e first get the list of unique users who ever logged in.
for every user
last |grep user | process data
and the other array with the login as an element reference is the duration counter.
The other option is to run the last command as many times as there are individual users
I.e first get the list of unique users who ever logged in.
for every user
last |grep user | process data
ASKER
Could you give me a few lines of sample code so that I have something to build of of? I'm not sure how to even start reallly.
last | awk ' { print $1 } ' | sort -fu | while read a; do
echo working with user $a:
last | grep $a | perl_script_to_get_user_sp ecificdata .pl #this script will output user:logins:duration
done
echo working with user $a:
last | grep $a | perl_script_to_get_user_sp
done
#!/usr/bin/perl
while (<STDIN>) {
#$_ will have each line
chomp(); #if exists remove the cr/lf from this line
@array=split(/\s+/,$_)
#$array[1] has the username
#$array[$#array] has the duration
#you need a line counter to count the number of logins.
#you then need to convert the duration reported into minutes and add it to a duration counter. Note the pattern of duration can be (hh:mm) or (d+hh:mm)
#Did you cover pattern match/data extraction?
}
print "User:$array[0] Had $login_count logins for a total duration of $duration_counter\n";
ASKER
So am i supposed to put this code at the top:
last | awk ' { print $1 } ' | sort -fu | while read a; do
echo working with user $a:
last | grep $a | perl_script_to_get_user_sp ecificdata .pl #this script will output user:logins:duration
done
Then paste lines 1-13 undernearth it? i am also using strict and it tells me that array and login_count_ are not valid.
We did cover pattern match. How is that going to be used /.
last | awk ' { print $1 } ' | sort -fu | while read a; do
echo working with user $a:
last | grep $a | perl_script_to_get_user_sp
done
Then paste lines 1-13 undernearth it? i am also using strict and it tells me that array and login_count_ are not valid.
We did cover pattern match. How is that going to be used /.
ASKER
Here is my exact eror message:
Unquoted string "awk" may clash with future reserved word at ./program7.pl line 29.
String found where operator expected at ./program7.pl line 29, near "awk ' { print $1 } '"
(Do you need to predeclare awk?)
Unquoted string "a" may clash with future reserved word at ./program7.pl line 29.
Unquoted string "pl" may clash with future reserved word at ./program7.pl line 31.
Unquoted string "done" may clash with future reserved word at ./program7.pl line 32.
syntax error at ./program7.pl line 29, near "awk ' { print $1 } '"
syntax error at ./program7.pl line 30, near "do
echo working with "
Execution of ./program7.pl aborted due to compilation errors.
Unquoted string "awk" may clash with future reserved word at ./program7.pl line 29.
String found where operator expected at ./program7.pl line 29, near "awk ' { print $1 } '"
(Do you need to predeclare awk?)
Unquoted string "a" may clash with future reserved word at ./program7.pl line 29.
Unquoted string "pl" may clash with future reserved word at ./program7.pl line 31.
Unquoted string "done" may clash with future reserved word at ./program7.pl line 32.
syntax error at ./program7.pl line 29, near "awk ' { print $1 } '"
syntax error at ./program7.pl line 30, near "do
echo working with "
Execution of ./program7.pl aborted due to compilation errors.
#!/usr/bin/perl
use warnings;
#use strict;
last | awk ' { print $1 } ' | sort -fu | while read a; do
echo working with user $a:;
last | grep $a | perl_script_to_get_user_specificdata.pl; #this script will output user:logins:duration
done;
while (<STDIN>) {
#$_ will have each line
chomp(); #if exists remove the cr/lf from this line
my @array=split(/\s+/,$_);
#$array[1] has the username
#$array[$#array] has the duration
#you need a line counter to count the number of logins.
#you then need to convert the duration reported into minutes and add it to a duration counter. Note the pattern of duration can be (hh:mm) or (d+hh:mm)
#Did you cover pattern match/data extraction?
}
print "User:$array[0] Had @$login_count_ logins for a total duration";
~
The two are two separate scripts.
awk and everything that follows is a bash/shell script
#!/bin/sh
last | awk ' { print $1 } ' | sort -fu | while read a; do
echo working with user $a:;
last | grep $a | perl_script_to_get_user_sp ecificdata .pl; #this script will output user:logins:duration
done;
The other processor is a perl script
Note that last and the perl script will run as many times as there are unique users in last.
awk and everything that follows is a bash/shell script
#!/bin/sh
last | awk ' { print $1 } ' | sort -fu | while read a; do
echo working with user $a:;
last | grep $a | perl_script_to_get_user_sp
done;
The other processor is a perl script
Note that last and the perl script will run as many times as there are unique users in last.
Oh, for strict you have to define the variables that will be used using
my $variable # at the top for global use variable or within the if/while as a local variable that will be redifined upon every entry into the if/while etc. block.
You need to use pattern match to extract the data from the duration.
i.e. how are you planning on adding an entry (03:23) and (2+02:20)?
You have to extract the information and convert it to a common unit.
usera pts/0 location date (03:23)
usera pts/1 location2 date (2+02:20)
What is the information for usera?
usera had 2 logins for a duration of 2days 5 hours and 43 minutes. or 3223 minutes or 53 hours and 43 minutes.
my $variable # at the top for global use variable or within the if/while as a local variable that will be redifined upon every entry into the if/while etc. block.
You need to use pattern match to extract the data from the duration.
i.e. how are you planning on adding an entry (03:23) and (2+02:20)?
You have to extract the information and convert it to a common unit.
usera pts/0 location date (03:23)
usera pts/1 location2 date (2+02:20)
What is the information for usera?
usera had 2 logins for a duration of 2days 5 hours and 43 minutes. or 3223 minutes or 53 hours and 43 minutes.
ASKER
We haven't covered scripts yet. I need everything to run and process in the Perl program.
Or you can use last | sort | perlscript
Note that in this case you have to check whether the user in the current line is the same as the user in the prior line. If it is not, you need to output data for the prior user and reset the counters and the user for the current user then continue processing.
Or
use
open LAST,"/usr/bin/last| awk ' { print $1 } ' | sort -fu " || die "Unable to run last command:$!\n;
while ($user=<LAST>) {
chomp($user);
open LAST3,"/usr/bin/last| grep $user |" || die "Unable to run last command a second time (inner loop):$!\n;
while (<LAST3>) {
chomp();
#process data here
} #close inner loop
close (LAST3)
print "user: $user Number of logins: $logins Duration: $duration\n";
} #close outer loop
close (LAST)
Note that in this case you have to check whether the user in the current line is the same as the user in the prior line. If it is not, you need to output data for the prior user and reset the counters and the user for the current user then continue processing.
Or
use
open LAST,"/usr/bin/last| awk ' { print $1 } ' | sort -fu " || die "Unable to run last command:$!\n;
while ($user=<LAST>) {
chomp($user);
open LAST3,"/usr/bin/last| grep $user |" || die "Unable to run last command a second time (inner loop):$!\n;
while (<LAST3>) {
chomp();
#process data here
} #close inner loop
close (LAST3)
print "user: $user Number of logins: $logins Duration: $duration\n";
} #close outer loop
close (LAST)
ASKER
Ok. I tried to modify it and this is what Im getting now":
Unquoted string "usr" may clash with future reserved word at ./program7.pl line 10.
Unquoted string "bin" may clash with future reserved word at ./program7.pl line 10.
Bareword found where operator expected at ./program7.pl line 10, near "" || die "Unable"
(Missing operator before Unable?)
Unquoted string "run" may clash with future reserved word at ./program7.pl line 10.
Bareword found where operator expected at ./program7.pl line 10, near "last command a"
(Do you need to predeclare last?)
Backslash found where operator expected at ./program7.pl line 10, near "$!\"
(Missing operator before \?)
Unquoted string "n" may clash with future reserved word at ./program7.pl line 10.
Not enough arguments for grep at ./program7.pl line 10, near "" || die "Unable to "
syntax error at ./program7.pl line 10, near "" || die "Unable to "
Unmatched right curly bracket at ./program7.pl line 31, at end of line
syntax error at ./program7.pl line 31, near "}"
Unmatched right curly bracket at ./program7.pl line 35, at end of line
Execution of ./program7.pl aborted due to compilation errors.
Unquoted string "usr" may clash with future reserved word at ./program7.pl line 10.
Unquoted string "bin" may clash with future reserved word at ./program7.pl line 10.
Bareword found where operator expected at ./program7.pl line 10, near "" || die "Unable"
(Missing operator before Unable?)
Unquoted string "run" may clash with future reserved word at ./program7.pl line 10.
Bareword found where operator expected at ./program7.pl line 10, near "last command a"
(Do you need to predeclare last?)
Backslash found where operator expected at ./program7.pl line 10, near "$!\"
(Missing operator before \?)
Unquoted string "n" may clash with future reserved word at ./program7.pl line 10.
Not enough arguments for grep at ./program7.pl line 10, near "" || die "Unable to "
syntax error at ./program7.pl line 10, near "" || die "Unable to "
Unmatched right curly bracket at ./program7.pl line 31, at end of line
syntax error at ./program7.pl line 31, near "}"
Unmatched right curly bracket at ./program7.pl line 35, at end of line
Execution of ./program7.pl aborted due to compilation errors.
#!/usr/bin/perl
use warnings;
#use strict;
open LAST,"/usr/bin/last| awk ' { print $1 } ' | sort -fu " || die "Unable to run last command:$!\n;
while ($user=<LAST>) {
chomp($user);
open LAST3,"/usr/bin/last| grep $user |" || die "Unable to run last command a second time (inner loop):$!\n;
while (<LAST3>) {
chomp();
#process data here
#while (<STDIN>) {
#$_ will have each line
#chomp(); #if exists remove the cr/lf from this line
my @array=split(/\s+/,$_);
#$array[1] has the username
#$array[$#array] has the duration
#you need a line counter to count the number of logins.
#you then need to convert the duration reported into minutes and add it to a duration counter. Note the pattern of duration can be (hh:mm) or (d+hh:mm)
#Did you cover pattern match/data extraction?
}
print "User:$array[0] Had @$login_count_ logins for a total duration";
} #close inner loop
close (LAST3)
print "user: $user Number of logins: $logins Duration: $duration\n";
} #close outer loop
close (LAST);
~
I've provided you with almost a step by step what you need to consider to get the results you want. can you provide a sample of code that you worked out?
I have a fully functional perl script that uses hash of hashes to go through.
Using last | sort | perl_script should be fairly simple to create.
What you need to know in perl is while (<STDIN>) {}
To go line by line. You then have to make sure to check whether the user reported in this line is the same as the user from the prior line.
You need to use split, the break up the line into its informational sections, username, duration.
You need to use pattern match to extract the relavent data from the duration so that you can then convert the reported duration into minutes.
the first occurance where the current user does not match the prior user, you must output the prior user's information and reset the counts.
I have a fully functional perl script that uses hash of hashes to go through.
Using last | sort | perl_script should be fairly simple to create.
What you need to know in perl is while (<STDIN>) {}
To go line by line. You then have to make sure to check whether the user reported in this line is the same as the user from the prior line.
You need to use split, the break up the line into its informational sections, username, duration.
You need to use pattern match to extract the relavent data from the duration so that you can then convert the reported duration into minutes.
the first occurance where the current user does not match the prior user, you must output the prior user's information and reset the counts.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
You effectively are looking at hash of hashes
users{login_name}->{logins
-> {duration}
You would need to convert the duration reported by last (hours:minutes) or (days+hours:minutes) into minutes.
fairly simple to do.