Finding user accounts not accessed for a specific number of days

Hi all,

Recently I came across a challenge of finding the user accounts lying around on servers and not being used so much. Our client has hundreds of AIX, RedHat, and Solaris servers.

For AIX, I have made a script which uses lsuser and a little bit of sed and awk to show the user accounts which are not accessed for say 30 days.

Problem is I am not able to come up with the same result for Linux and Solaris servers.

For Linux, I'm using this to see the last login time for a specific user:

utmpdump /var/log/wtmp | grep user | tail -n1

And, for Solaris, I'm using this for the same:

last -f /var/adm/wtmpx | grep user | tail -n-1

But, I need to think a way of getting a list of users who have not logged in for 30 days for Linux and Solaris servers.

So here I am, asking for help from you guys. Thanks :slight_smile:

----------------------
Update: I have come up with the below script for Linux and Solaris for the same issue. I am pasting here for those people who just bump into this thread from search engines.
Hope this script helps.

#!/bin/bash  # this script searches for the user ids which have not been used for a specific # number of days   # the number of days to be monitored expdays=30 expiry=$(( 86400*$expdays ))  LOG1=/tmp/inactive_usr_$expdays_days.$( date '+%m-%d-%Y' ).log LOG2=/tmp/never_logged_usrs.$( date '+%m-%d-%Y' ).log tmp1=/tmp/tmp1.log.$$  # list out the accounts which can be used to log in to the server  cat /etc/passwd | grep -Ev ^"root|daemon|nobody|adm|sys" | cut -d ":" -f1 >>$tmp1  # date and time calculation with respect to unix epoch  year=$( date +%Y )  today=$( date +%s )  # now, for each of the user listed above, run a check if the last logged in time exceedes the specified number of days.  cat $tmp1 | while read usr; do         umnt=$( last -1 $usr | head -1 | awk '{ print $5 }' )         uday=$( last -1 $usr | head -1 | awk '{ print $6 }' )         uhour=$( last -1 $usr | head -1 | awk '{ print $7 }' | cut -d ":" -f1 )         umin=$( last -1 $usr | head -1 | awk '{ print $7 }' | cut -d ":" -f2 )          # the below line checks and stores the IDs which were never used         if [ ! $uday ] || [ ! $uhour ] || [ ! $umin ]; then             echo "$usr:__NeveR__" >>$LOG2         else             llogin=$( date +%s -d"$umnt $uday, $year $uhour:$umin:01" )             mini=$(( $today-$llogin ))             if [[ $mini -gt $expiry ]]; then                 login=$(( ($today-$llogin)/86400 ))                 echo "$usr:$login" >>$LOG1             fi         fi done  rm -f $tmp1

In Linux I can think of using the following command in some kind of efficient looping for each user

last -t YYYYMMDDHHMMSS <user>

1 Like

Some systems have an empty file called $HOME/.lastlogin that is "touched" each time the user logs in.

1 Like

finger also provide last or no login info, or on since.

On POSIX systems

last -1 username

Gives full information on the last login for a given user

1 Like

Im a bit bit tired so I may say a load of crap...IMHO
rather than:

last -f /var/adm/wtmpx | grep user | tail -n-1

why not e.g

 $ finger -sw user|tail -1
 $ last user|head -1               

But you could read in a loop all the lines of just the output of last till the date you want in a file, keep the first field (user name) make them uniq and use that to against user database

1 Like

Since a user can become active through non-logins like rsh cmd, ssh cmd, sudo, su or set-uid, it'd be nice if there was a way to track this, but it would add overhead. Every time anyone uses a set-uid command, the user, maybe root, gets a hit. Time sharing accounting used to be a big deal, but not so much now.

1 Like

Thank you all for your reply. This weekend I'm planning to sit tight and write a script for this. Once done, I'll post that here and would love to get your reviews. :slight_smile:

---------- Post updated 09-17-11 at 04:13 PM ---------- Previous update was 09-16-11 at 07:45 PM ----------

Well thanks for your input guys. Here is the bash script I have written for our Linux and Solaris servers. It's almost similar to the ksh script I wrote for the same purpose on AIX servers. The difference is with AIX's lsuser command, it was easy for me to get user details.

Review the code and let me know your thoughts :slight_smile:

#!/bin/bash

# this script searches for the user ids which have not been used for a specific
# number of days


# the number of days to be monitored
expdays=30
expiry=$(( 86400*$expdays ))

LOG1=/tmp/inactive_usr_$expdays_days.$( date '+%m-%d-%Y' ).log
LOG2=/tmp/never_logged_usrs.$( date '+%m-%d-%Y' ).log
tmp1=/tmp/tmp1.log.$$

# list out the accounts which can be used to log in to the server

cat /etc/passwd | grep -Ev ^"root|daemon|nobody|adm|sys" | cut -d ":" -f1 >>$tmp1

# date and time calculation with respect to unix epoch

year=$( date +%Y )

today=$( date +%s )

# now, for each of the user listed above, run a check if the last logged in time exceedes the specified number of days.

cat $tmp1 | while read usr; do
        umnt=$( last -1 $usr | head -1 | awk '{ print $5 }' )
        uday=$( last -1 $usr | head -1 | awk '{ print $6 }' )
        uhour=$( last -1 $usr | head -1 | awk '{ print $7 }' | cut -d ":" -f1 )
        umin=$( last -1 $usr | head -1 | awk '{ print $7 }' | cut -d ":" -f2 )

        # the below line checks and stores the IDs which were never used
        if [ ! $uday ] || [ ! $uhour ] || [ ! $umin ]; then
            echo "$usr:__NeveR__" >>$LOG2
        else
            llogin=$( date +%s -d"$umnt $uday, $year $uhour:$umin:01" )
            mini=$(( $today-$llogin ))
            if [[ $mini -gt $expiry ]]; then
                login=$(( ($today-$llogin)/86400 ))
                echo "$usr:$login" >>$LOG1
            fi
        fi
done

rm -f $tmp1