How to calculate time

Hello Guys,
I am trying to calculate total hours and minutes a given user has used the system since the beginning of the current month.

#!/usr/bin/sh
hr=0
min=0
last $1 | grep -w `date "+%b"` | grep -v '\(0[2-9]:.*\)' | grep -vw sshd | cut -c 66-
| tr -d "[ ]\(\)" | cut -f1 -d ":" | grep -v '[a-z].*' | while read line
do
        hr=`expr "$hr" + "$line"`
        echo User $1 spent total $hr
done
last $1 | grep -w `date "+%b"` | grep -v '\(0[2-9]:.*\)' | grep -vw sshd | cut -c 66-
| tr -d "[ ]\(\)" | cut -f2 -d ":" | grep -v '[a-z].*' | while read line
do
        min=`expr "$min" + "$line"`
         if [ $min -ge 60 ]
        then
                min=`expr "$min" - 60`
                hr=`expr "$hr" + 1`
         echo User $1 spent $hr hours and $min minutes the current month.
        continue
        fi
done
echo "User $1 spent $hr hours and $min minutes the current month."

My code is working fine. I have problem with variable. I can't use variable outside loop. It showing 0 hours and 0 minutes.

Thanking You,

Please display the output of your "last" command.

Yes, the variable will not be available... this is a known issue... If you see your code, while is piped from the cut command so it has its own shell(subshell) where the execution happens...

--ahamed

One of the advantages that Korn shell has over bash is that this is not a problem for it. If you aren't required to use bash, then you might consider switching and using Kshell.

It's not a "bash" thing, it's an "everything except certain versions of ksh" thing. Demanding a specific version of a specific shell everywhere you go doesn't strike me as a good idea.

Two solutions.

1) temp file:

a | b | c | d > /tmp/$$
while read LINE
do
...
done < /tmp/$$
rm /tmp/$$

2) refactor your code so you're not using 9-long pipe chains. This is probably a good idea anyway.

  1. New Features in Bash (4.2)
    ...
    t. There is a new `lastpipe' shell option that runs the last command of a pipeline in the current shell context. The lastpipe option has no effect if job control is enabled.

Demanding a specific version of a specific shell everywhere you go doesn't strike me as a good idea.

Hello Guys,

Thanks for your valuable comments. Is there any solution without creating temp file?

My two cents, I would have used awk to process the output. No intermediate file, shell independence, and fewer total processes:

#!/usr/bin/env ksh

last $1 | awk -v month="$(date +%b)" '
   /wtmp/  ||  /still logged in/ || / sshd / { next; }

      NF > 0  &&  $(NF-5) == month {
        gsub( "\\(", "", $NF );         # ditch parens
        gsub( "\\)", "", $NF );

        if( index( $(NF), "+" ) )       # days+hr:min
        {
            split( $NF, b, "+" );       # capture days, leave hr and min in a
            days += b[1];
            split( b[2], a, ":" );
        }
        else
            split( $NF, a, ":" );       # no days, just caputre hr and min

        hr += a[1];
        min += a[2];
    }

    END {
        eh = int( min/60 );     # extra hours
        hr += eh;
        min -= 60 * eh;

        ed = int( hr/24 );      # extra days
        days += ed;
        hr -= 24 * ed;
        printf( " %dd%dh%dm\n", days, hr, min );   # print in XdXmXh notation
    }
'
exit $?

I do not understand the intent of this part of your pipe: grep -v '\(0[2-9]:.*\)' . Are you only wanting to look at sessions that lasted more than 10 hours or less than 2 hours?

Hi Agama,

Thanks for your reply. My code [code] grep -v '\(0[2-9]:.*\)' filter output if user is logged in more than 2 hours. My code is working. Only value of variable outside loop is bothering me.

Thanking You,