Write a scripts to kill idle user for 60 min. & email user list to admin in text file

Folks,

I have written one script for following condition by referring some of online post in this forum. Please correct it if I'm missing something in it. (OS: AIX 5.3)

  1. List the idle user. (I used whoidle command to list first 15 user and get username, idle time, pid and login time). Any other suggestion to get all the user at once including above things?
  2. Exclude few users from list (system user and admin user)
  3. Calculate idle time(if user is more than 60 min idle)
  4. Make entry of that user in log file (If possible I want to create text file)
  5. Email log file to admin
  6. Sleep for 5 min. after emailing total list of user to admin
  7. Kill the users in list
  8. Loop it to reach next 15 users. (If possible I want to get rid of this condition by following all idle user list command with pid's)
IDLE_USER=/tmp/idleusers.log
idletimeslist=$(whoidle | awk '{print $4}')
maxidletime = 0:59

idletimes= $(grep -v^"root|daemon|bin|sys|adm|nobody|abc|pqr" $idletimeslist)


for numbers in $idletimes;do

if [[ $(echo "$numbers" | grep : ) == $maxidletime]];then
getline=$(whoidle | grep $numbers)
user=$(echo $getline | awk '{print $1}')
processid=$(echo $getline | awk '{print $5}')
started=$(echo $getline | awk '{print $3}')
echo $user' '$processid' '$started' '$number >> $IDLE_USER
fi
done

# Send Email notification
# Please suggest email command to email log file to admin email id.
# Also can I convert log file to text file? (word file)

sleep 300

pidlist= awk '{print $2}' $IDLE_USER
for pid in $pidlist;do
kill $pid
done
# I have no idea how I can loop it to satisfy condition '8'. Do i need true or false flag #for it?

I need to put this code in production as soon as possible.
Expert please throw some light on it.
Thanks in advance.
Sumit

To address the 5th point of your steps, just use the mail utility if you have it installed on your system. Check its man page for detail.
As far as the 8th point, I would approach it in the following manner;

Outside the loop do this:

if [ "`eval echo $idletimes`" != "" ]; then
  eval TUSRS=`wc -l $idletimes |awk '{ print $1 }'`
  USRS=""
fi

Inside the loop to the following:

if [ "`evel echo $USRS`" = "" ]; then
  eval USRS=`ehco $idletimes |sed 15q`
else
  if [ `eval echo $TUSRS` -gt `eval echo $USRS` ]; then
     PLINE=`eval expr '$TUSRS' - '$USRS'`
     NUSRS=`sed '$USRS,$PLINE!d'`
  fi
fi

The last block of code needs to be within a loop for it to work appropriately. This should work fine, but if you have problems let me know. I have not tested it because I have no access to an AIX server.
By the way, the points that you have already taken care of can be improved to be more efficient...

1 Like

Can you share the sample output for the command: whoidle ?

With it, we can easily help you.

@ guto: Thank you for reply. What will be more efficient way you can suggest. Can you put it in script? Thanks again.

@ rdcwayx:
whoidle command look like below.... it gives first 15 idle users from system. 'w' command not gives pid to kill so I used whoidle.

Here are few users from system.

User         Terminal   LoginDate     Idle      PID      Location
op           pts/5      Mar 25 06:13  6:15      125922   (XTSCR1)
wk           pts/191    Mar 25 10:44  1:56      184744   (192.203.5.32)
doc          pts/178    Mar 25 11:41  1:14      128836   (192.139.4.125)
aperez       pts/149    Mar 25 11:06  1:13      284380   (192.139.4.106)
kgraff       pts/150    Mar 25 11:07  1:12      273774   (192.135.3.86)

sumit30,
if I was you, based on the output of 'whoidle', I would probably lunch it with the option to get all the idle users in the system and save it to a file within the same directory with the script. supposing the option is '-a', it would something like this: 'whoidle -a' >ALL_IDLE_USERS

this code has not been tested on an AIX system. I tested it on my laptop using the sample data you supplied and it's working like a charm.

------------------------beginning script-------------------------
DATE=`date +%D`
TIME=`date +%T`
HNAME=`uname -n`
LFILE=$(uname -n)_Idle_Users_$(date +%h)_$(date +%d)_$(date +%y).txt
SUBJECT="$HNAME Idle User List"
EMAIL="admin@yourdomain.com"
HEAD=`cat IDLE_USERS |sed q`
cat ALL_IDLE_USERS |sed '1d' |egrep -v "root|daemon|bin|sys|adm|nobody|abc|pqr" >IDLE_USERS
IDL=`cat IDLE_USERS |awk '{ print $6}'`
echo  -e "---------------------------------------------- \nDATE: $DATE\t\t  TIME:  $TIME\n-----------------------------------------------------------------------------------------"  > $LFILE
echo -e "$HEAD\t\tStatus" >> $LFILE

for DL in $IDL
  do
    H=`echo $DL |cut -d: -f1`; M=` echo $DL |cut -d: -f2`
    if [ $H -gt 0 ] || [ $M -eq 60 ]; then
       kill -15 $PID;
       CLINE=`grep -w $DL ALL_IDLE_USERS`
       RUNNING=`ps -p $PID |sed '1d'`
       if [ "$RUNING" == "" ]; then
          echo -e "$CLINE \tKilled" >> $LFILE
       else
          echo -e "$CLINE \tRunning" >> $LFILE
       fi
    fi
done
echo -e "-----------------------------------------------------------------------------------------" >> $LFILE

if [ -s $LFILE ]; then
   mail -s $SUBJECT $EMAIL < $LFILE
   touch $LFILE.txt
fi
----------------end script---------------

this is an elegant way of resolving your problem without the need for any complications: such as the 8th point.
in my opinion 8th point isn't necessary. thus, the code that I supplied to you the other time isn't needed because you are not dealing with a file or a variable that must continue growing.
for instance, if you were picking the idle users from a certain system-log-file which must continue growing as the system is running and logging various events, then you would need to have a way to loop through that file as long as it continues to increase. but your problem is much simple based on what I perceive from your explanation.
as far as I know, the technique that intend to use on point 8 is normally used to monitor specific regexs in a log-files.
NEXT TIME, I'M GONNA CHARGE YOU A FEE OR SOMETHING! lol; I am at home for over a year. I need to get paid....