LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   a script to create login/day stats, based on output of last (https://www.linuxquestions.org/questions/programming-9/a-script-to-create-login-day-stats-based-on-output-of-last-774001/)

wet_weasel 12-07-2009 09:59 AM

a script to create login/day stats, based on output of last
 
hey LQ.

i wont lie to you - this is about homework. :)

but i will not be asking you for a solution, merely discussing my own, which, in my eyes seems a bit overkill. (why? the course i'm forced to be doing at uni introduced us to _reeeaaaally_ __basic__ bash stuff, the lecturer isn't even aware of printf existing as a bash builtin - echo = GOD. so as you see, he isn't too enlightened in this particular field. but enough of that.)

we were tasked with writing five bash scripts, each of them pretty much dull - the usual ifs, checking for read/write access etc etc. pretty much all four are ENTIRELY about using ifs witht the right switches/flags.

but.

one script is supposed to take the output of last and basing on it, print out the number of logins took place each day.

no problem, right? just read it line by line, awk out the date fields and use a simple counter to count how many times that date occurs. rinse and repeat for every day.

the problem is, we're not supposed to know what awk is. not even what a field is.

here is my question - am I right to think that my awk-based solution is way too complicated for the job and there's something painfully simple i'm missing?

how would you do this?

(not asking for a ready to use script, i can do those on my own. asking for other solution ideas!)

so, what do you think?

SethsdadtheLinuxer 12-07-2009 10:17 AM

what about grep and wc in combination? That's probably what the instructors are looking for.

wet_weasel 12-07-2009 11:17 AM

hmm, good thinking.

even though simpler when it comes to the tools used, this one seems a bit more complicated when it comes to the script itself.

seems i'd have to blindly grep for dates, day after day (a lot of null results when checking rarely used accounts).

this brings up another problem - how far back does last look? i'm confused here, because the system I'm working on atm doesn't even have a /var/log/wtmp file (mac os 10.5) and yet, last somehow manages to gather up all the info.

one more thing that I do not understand: if I do a simple last ben > bens_logins a couple of times in a row, the bens_logins file is different (size-wise) every time. this is also shown by running last | wc -l a few times in a row - usually the number of lines goes up almost twice, and i'm definitely NOT doing that many logins in those few seconds it takes to run last. in fact, i'm not doing any extra logins at all.

why is this?

catkin 12-07-2009 11:44 AM

As the last command outputs logins in date order and, once the reboot lines and footer are discarded, the day-of-month is always the 6th space-separated field it can be done entirely within shell script.

I figure from the way you asked the question you will study any solution given and thus learn even if you haven't actually written it yourself so I'll break the normal homework questions rule and give a solution (but it's not tested so you may have some learning-by-debugging :) including avoiding repeating the previous count if the final record is a reboot and handling the last command's final two output lines).
Code:

last_day=0
count=0
while read line
do
    if [[ "${line#reboot}" == "$line" ]]; then
        array=( $line )
        day="${array[5]}"
        if [[ $day != $last_day ]]; then
            [[ $count -ne 0 ]] && echo "On day $last_day: $count logins"
            last_day=$day
            count=1
        else
            let count=count+1           
        fi
    fi
done <<< $( last )
echo "On day $last_day: $count logins"

Please ask about any features of this script that are still puzzling after research.

wet_weasel 12-07-2009 12:42 PM

thank you, catkin!

for now, there are two things I had to change in your script. one, the day is array[4] and two
Code:

done <<< $( last )
didn't work well (it sends last's output as one, single line), so I had to do a little workaround using a temporary file (not sure if this is good..):
Code:

last user > logins.tmp
while read line
do
        *code*
done < logins.tmp

which works fine.

the last 'problem' is that your script doesn't deal with months, but i think i'll be able to add that tiny bit of functionality without a problem..

one question so far (pertaining to the done <<< $( last )) line. what is the difference between a single < and <<< ?

catkin 12-07-2009 03:33 PM

Quote:

Originally Posted by wet_weasel (Post 3782983)
one question so far (pertaining to the done <<< $( last )) line. what is the difference between a single < and <<< ?

A single < takes input from a file while <<< takes input from whatever the following expression evaluates to. You could try changing that part of the script to <<< "$( last )" because it might overcome the problem of the expression generating a single line.


All times are GMT -5. The time now is 01:33 AM.