The command last

Hello All,

I would like to ask your kind help. Could you please advise how can I identify and printout all users, who has logged to our server from more than 10 different computers/machines by using the command last?

Thank you in advance for your help.

Janmesz

First of all, last data is easily circumvented. So, while last is "ok", a person can "login" into your host and not be recorded in the wtmp/utmp file.

What is last not showing you? It will show all "proper" logins. But nothing saying you have a wtmp unaware path for login defined.

By default last will show the userid, the terminal, the DISPLAY (sort of a hack)/location and the time and duration.

Again, let me emphasize that wmtp writing is an optional thing.... and that well behaved logins will log something there.

1 Like

Please, try:

last -ai | perl -nale '
    push @{$user{$F[0]}}, $F[$#F] unless grep {$_  eq $F[$#F]} @{$user{$F[0]}};  
    END{for(keys %user){print if @{$user{$_}} > 10}}'

---------- Post updated at 05:43 PM ---------- Previous update was at 04:24 PM ----------

A bit simpler:

last -ai | perl -nale '$user{$F[0]}{$F[$#F]}++; END{for(keys %user){print if keys %{$user{$_}} > 10}}'

[/CODE]

1 Like

awk version

last -ai | awk '{ user=$1;ip=$NF;if (t[ user ip ] == "") { c[ user ]++;t[ user ip ]=1 }} END { for (name in c) { if (c[ name ] > 10) { print name }}}'
1 Like

The following is little shorter and little more precise, and also works on Solaris (with nawk or /usr/xpg4/bin/awk).

last -a | awk '$NF!~/^[^:]*:[0-9]+(\.|$)/ && !uh[$1,$NF]++ { uc[$1]++ } END { for (u in uc) if (uc>10) print u }'
1 Like

Thank you very much for all of you for these solutions, which were all functionable except of the last one. Much appreaciated your responses, however could you please advise how may I get the following output from this filter:

"Output: 'name number of different computers/machines'"

Example:

Output: 'smith 23'
Output: 'mccallister 22'
Output: 'taylor 22'
Output: 'bush 21'
Output: 'casale 20'
Output: 'grant 19'
...

Thank you in advance for your advice.

Janmesz7

How about

last -a | awk '$NF ~ /.*\..*\..*\..*/ && !T[$1,$NF]++ {US[$1]++} END {for (u in US) print u, US}'

Hi RudiC,

I have got this error message:

T[: Event not found.

Any idea about this?

Thank you

That's a bash error message (that you did not print entirely) when it fails to match a pattern in the history.
You seem not to have copied the proposal as posted. Are all quotes present?

Please, try:

last -ai | perl -nale '$user{$F[0]}{$F[$#F]}++; END{for(keys %user){keys %{$user{$_}} > 10 and print "$_: ", scalar keys %{$user{$_}}}}'

or:

last -ai | perl -nale '$user{$F[0]}{$F[$#F]}++; END{for(keys %user){$c = keys %{$user{$_}}; $c > 10 and print "$_: ", $c}}'

This is a tcsh error. It even does history substitution within 'ticks'.
Put a space after the ! or replace the ! (not) operator by 0== (equal to 0).

Hi Aia,

I am so thankful for your response, however your code generates different output as I need.

Your output:
smith: 23
mccallister: 22
taylor: 22
bush: 21
casale: 20
grant: 19

The needed output:
Output: '"name" 23'
Output: 'smith 23'
Output: 'mccallister 22'
Output: 'taylor 22'
Output: 'bush 21'
Output: 'casale 20'
Output: 'grant 19'

May I ask you to modify your code to obtain the needed output format?

Thank you in advance for your kind help.

Janmesz7

Please do it yourself! Play a bit with the print statement.

Certainly.

Try:

last -ai | perl -nale '$user{$F[0]}{$F[$#F]}++; END{for(keys %user){$c = keys %{$user{$_}}; $c > 10 and print "Output: \047$_ $c\047"}}'