Ruby one-liner to count logins in Linux last command

count logins in last command

If you want to take the output of the Linux last command, and get a count of how many times each user connected to your server, this script will do.

sample input

tommytrojan      sshd         abc.def Fri May 15 13:30 - 13:30  (00:00)joebruin      sshd         ddd.eee Fri May 15 13:30 - 13:30  (00:00)joebruin      sshd         ddd.eee Fri May 15 13:30 - 13:30  (00:00)janebruin      sshd         ddd.eee Fri May 15 13:30 - 13:30  (00:00)

sample output

Total entries: 4joebruin = 2janebruin = 1tommytrojan = 1

script and explanation

last | ruby -ane 'BEGIN{rows=0; a={}}; next if $F[0].nil?; a[$F[0]]||=0;a[$F[0]]+= 1; rows += 1; END{puts "Total entries: #{rows}" ; a.sort_by{|k,v|v}.reverse.each{|k,v| puts "#{k} = #{v}"} }'

  • ruby -e executes the following script; -n loops; and -a splits input and outputs into $F array
  • BEGIN block is necessary to initialize row count and a hash, where we’ll store counts
  • next if $F0.nil?; is necessary, because at least one of our input lines had no user field.
  • $F0 gives us first field in input line.
  • a[$F0]||=0; initializes hash location to 0 if it hasn’t been used yet
  • a[$F0]+= 1; increments user access count in hash
  • END block lets us print our report.
  • a.sort_by{|k,v|v}does a sort by the counts, not by the user names. a.sort would have been enough if we just wanted it sorted by the key, ie: usernames.
  • reverse.each{|k,v| puts “#{k} = #{v}”} reverses the sort to get descending order, and outputs the key (k) and value(v), e.g. username = access count.

NOTE: My colleague did the same thing in this shell script. And his script includes the line with the missing user field.

last | cut -d" " -f1 | sort | uniq -c | awk '{print $1" " $2}' | sort -nr