0

I'm getting the time of the last session of an specific user using the last command like below:

last -aiF -n 1 fakeuser

The output of this command is something like:

fakeuser pts/0 Tue Nov 27 11:03:19 2018 - Tue Nov 27 11:14:57 2018 (00:11) 999.999.99.999

My question here is about the session time ((00:11) in the example). Are there any way to get this time in seconds?

I know that I can calculate it based on the login and logout time, but I'm looking for some solution directly in the last command, since I didn't found anything in the man entrance for the command neither in the web.

FYI, I'm working with Debian 9.5, but I believe that some solution for it should work in any distribution.

Side problem for the perfect answer (I identified it after the first answer here): How to identify the sessions that lasted less than a minute?

  • Just to clarify, you say "I'm looking for some solution directly in the last command" -- does that mean you'd be satisfied with a (potential) answer of "You can't", and that a post-processing answer (along the lines of last | some code) would be unacceptable ? – Jeff Schaller Dec 4 '18 at 19:12
  • @JeffSchaller answers including some post-processing are totally fine. I didn't found any command to do it – James Dec 4 '18 at 20:44
1

If I recall correctly, the field you are interested in is usually in the format Days+HH:MM, to convert that into seconds we can do something like this:

last -aiF -n 1 fakeuser | \
awk '{gsub(/\(|\)/, "", $14); print $14}' | \ 
awk -F'[:+]' 'length($0) != 0 {if(length($3) == 0) {$3=$2; $2=$1; $1=0} {print ($1 * 86400) + ($2 * 3600) + ($3 * 60)}}'

The first line is your last command.

In the second line we isolate the field you want which appears to be field 14 from your command output.

The third line has all the action. The delimiter is set (-F) to split fields on the plus (+) and colon (:) signs. We then test to make sure the line is not empty (length($0) != 0). The next bit (if(length($3) == 0) {$3=$2; $2=$1; $1=0}) is a quick trick to normalize any line into three fields, days, hours, and minutes. The rest ({print ($1 * 86400) + ($2 * 3600) + ($3 * 60)}) is simply the conversion into seconds (86400 seconds in a day, 3600 seconds in an hour, 60 seconds in a minute).

There may be an easier way, but this is what I came up with while messing with this over my lunch.

  • It works fine (with some adaptations) for most of my cases, thank you for remember me about all awk possibilities. Anyway, here is a side problem: Are there any way to know this time if the session lasted less than a minute? – James Dec 6 '18 at 13:50
  • 1
    I guess you could assume that if there is an entry that shows 00:00, that it would always be less than a minute. If the user shows up in last, they were logged in for more than zero seconds. If the result of the awk script is zero minutes, that would indicate they were logged in for less than 60 seconds. Am I missing an edge case? – GracefulRestart Dec 6 '18 at 18:05
  • I was thinking about some way to find how many seconds has the user session taken, for sessions with less than a minute. In these cases, the last command gave me the 00:00 result, but it looks like a limitation of the last command itself, not exactly an edge case. – James Dec 6 '18 at 19:06
1

GracefulRestart's awk solution to the question is excellent; as you noted in your comments to his answer the last command isn't quite granular enough. But, assuming that auth.log on debian is similar enough to what I see on Ubuntu you could so some maths based on the data there.

I appreciate that this is not an answer, but it still may be useful to you.

I filtered a bunch of lines out of /var/log/auth.log, they pertain to both local and ssh logins.

cat auth.log
2018-12-06T07:28:00.487714+13:00 server systemd-logind[944]: New session 2597 of user tink.
2018-12-06T08:34:16.360766+13:00 server login[29537]: pam_unix(login:session): session opened for user tink by LOGIN(uid=0)
2018-12-06T08:34:16.372714+13:00 server systemd-logind[944]: New session c4 of user tink.
2018-12-06T08:34:20.960596+13:00 server login[29537]: pam_unix(login:session): session closed for user tink
2018-12-06T08:36:01.197712+13:00 server systemd-logind[944]: Removed session 2597.

Here's a (convoluted) awk-script ..

cat session.awk
{
  if( $0 ~ /systemd-logind.+New session/  && $0~user ){
      start[$6]=$1
    }
  if( $0 ~ /systemd-logind.+ Removed session/ && start[gensub(/([0-9]+).*/, "\\1", "1", $6)] != ""  ){
      tmp = start[gensub(/([0-9]+).*/, "\\1", "1", $6)]
      cmd = "date +%s -d ";
      cmd  $1 | getline outa;
      cmd " "  tmp | getline ina;
      close( cmd )
      printf "%s was logged in for %s seconds\n", user, outa-ina
    }
  if( $0 ~ /login.+ session opened/  && $0~user ){
      start[gensub(/[^0-9]+([0-9]+).*/,"\\1","1",$3)]=$1
    }
  if( $0 ~ /login.* session closed/  ){
      tmp = start[gensub(/[^0-9]+([0-9]+).*/,"\\1","1",$3)]
      cmd = "date +%s -d ";
      cmd  $1 | getline outa;
      cmd " "  tmp | getline ina;
      close( cmd )
      printf "%s was logged in for %s seconds\n", user, outa-ina
    }
}

Running that against the snippet above:

awk -v user=tink -f session.awk sessions
tink was logged in for 4 seconds
tink was logged in for 4081 seconds

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.