The UNIX and Linux Forums  


Go Back   The UNIX and Linux Forums > Top Forums > Shell Programming and Scripting
.
google unix.com



Shell Programming and Scripting Post questions about KSH, CSH, SH, BASH, PERL, PHP, SED, AWK and OTHER shell scripts and shell scripting languages here.

More UNIX and Linux Forum Topics You Might Find Helpful
Thread Thread Starter Forum Replies Last Post
su ?? Who logged in First ?? varungupta UNIX for Advanced & Expert Users 2 01-24-2008 04:10 PM
logged out users roshni Post Here to Contact Site Administrators and Moderators 1 07-06-2007 04:02 AM
Finding last time users logged in jyoung UNIX for Dummies Questions & Answers 11 04-20-2005 03:03 PM
know who logged and logged out with their timings vkandati UNIX for Dummies Questions & Answers 3 03-09-2005 10:04 AM
Is user logged on?? provo UNIX for Dummies Questions & Answers 1 12-07-2001 05:41 PM

Closed Thread
English Japanese Spanish French German Portuguese Italian Dutch Swedish Russian Norwegian Hungarian Hebrew Danish Bulgarian Greek Powered by Powered by Google
 
LinkBack Thread Tools Search this Thread Rate Thread Display Modes
  #1 (permalink)  
Old 04-23-2007
ughosting ughosting is offline
Registered User
  
 

Join Date: Apr 2007
Posts: 3
Last time logged in

Working in AIX (so no date -d)

How can i display all the users who have not logged in for more than 40 days?

A small quick script would be usefull, my scripts are always taking to long to execute, even before they are finished.

Many thanks!
  #2 (permalink)  
Old 04-25-2007
jim mcnamara jim mcnamara is offline Forum Staff  
...@...
  
 

Join Date: Feb 2004
Location: NM
Posts: 5,794
Old C code to check /var/adm/wtmp - like the last command. It may compile/run on your box if the /var/adm/wtmp exists and it's not /var/adm/wtmpx - a different format.


Code:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <utmp.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>
#include <errno.h>

/* error macro */
#define ck(x) if ((x)==NULL) \
{barf("Memory/File error");}

/* limits */
#define USER_NAME_LEN 8
#define MAX_USERS 2000

/* array of usernames and times */
typedef struct
{
	char user[12];
	time_t logtime;
} ulog_t;
ulog_t array[MAX_USERS]={ {0x0}, 0 };

/* exit point for errors */
void barf(const char *msg)
{
	perror(msg);
	exit(EXIT_FAILURE);	
}

/* return size of file in bytes */
size_t filesize(const int fd)
{
	struct stat st;

	if(fstat(fd, &st) == (-1) )	
		barf("Cannot stat file");			

	return st.st_size;
}
/* return time_t seconds for ndays in the past */
time_t days_ago(const time_t ndays)
{
	time_t then=0;

    errno=0;
    then=time(NULL);
	if(then == (time_t)-1 && errno)	
		barf("");		
	then-=(86400 * ndays);
			
	return then;
}

/* map the utmp file into memory */
void *mappit(FILE *u, size_t ulen)
{
	void *addr=mmap((void *)0, ulen, PROT_READ, MAP_PRIVATE, fileno(u),0);

	if (addr==MAP_FAILED)
		barf("mmap failed");		
	
	return addr;
}
/* unmap file */
int unmappit(void *addr, size_t len)
{
	if( munmap(addr,len)==(-1))
		return 1;
		
	return 0;	
}
/* find user in array, change time or (if not found) add to array */
void find(const struct utmp *src, int *cnt)
{
	int i=0;
	int found=0;
	int limit=*cnt;	
	char tmp[10]={0x0};

	snprintf(tmp, USER_NAME_LEN+1, "%s",src->ut_user);
	if(strlen(tmp)> 0 )
	{
		for(i=0; !found && i < limit; i++)
		{
			if(strncmp(tmp, array[i].user, USER_NAME_LEN)==0)
			{
				found=1;
				if(src->ut_time > array[i].logtime)
					array[i].logtime=src->ut_time;					
			}
		}		
		if(found==0)
		{
			memcpy(array[limit].user, tmp, USER_NAME_LEN);			
			array[limit].logtime=src->ut_time;			
			limit++;
		}			
		*cnt=limit;
    }
}

void setup_array(const void *addr, int *arrlen, const size_t ulen)
{
	
	int i=0;
	int max=ulen/sizeof(struct utmp);
	int cnt=0;
	const struct utmp *f=(const struct utmp *)addr;

	for(i=0; i<max; i++, f++)
	{
		if(f->ut_type==USER_PROCESS && strlen(f->ut_user))
		{
			find(f, &cnt);
		}
	}
	*arrlen=cnt;
}
int between(const time_t ckval, const time_t low, const time_t high)
{
	int retval=(ckval >= low && ckval <= high);
	return retval;
}

int search(const time_t low_limit, const time_t high_limit, int arrlen)
{
	int i=0;
	char tmp[80]={0x0};
	time_t lt=0;
	ulog_t *p=array;

	for(i=0; i < arrlen; i++, p++)
	{
		if( (high_limit && between(p->logtime, low_limit, high_limit)) ||
			(!high_limit && p->logtime < low_limit) )
		{
			lt=p->logtime;
			strftime(tmp, sizeof(tmp), "%c", localtime(&lt));
			printf("%s: last login %s\n", p->user, tmp);
		}
	}
	
	return 0;
}

/*************************
* 
* search for the last time each one logged on
* if logon in time range prt it
***************************/

int process(FILE *u, const time_t low_limit, const time_t high_limit)
{
	int retval=0;
	size_t ulen=filesize(fileno(u));
	int arrlen=0;
	void *addr=mappit(u, ulen);

	setup_array(addr, &arrlen, ulen);
	retval=search(low_limit, high_limit, arrlen);
	retval|=unmappit(addr, ulen);
    
	return retval;
}



/*
   first argument req'd: # days
   read from /var/adm/wtmp - (file used by last)
   print all users with last logins < low_limit or with
         last logins between low_limit and high_limit when 
         high_limit is non-zero
*/
int main(int argc, char **argv)
{
	int retval=0;
	const time_t low_limit= (argc>1) ? days_ago(atoi(argv[1])): 0;
	const time_t high_limit=(argc>2) ? days_ago(atoi(argv[2])): 0;
	FILE *u=fopen("/var/adm/wtmp", "r");

 	ck(u);
	if ( low_limit > 0 && (high_limit==0 || high_limit >= low_limit))
		retval=process(u, low_limit, high_limit);
	else
	{
		fprintf(stderr,
			"Bad parameters.\n\tONE required: <number days ago>\n\tOptional: <most recent day>\n");
		fprintf(stderr,"     usage: utmp 10 5\n");	
		retval=1;
	}
    
	return retval;
}

  #3 (permalink)  
Old 04-25-2007
jgt jgt is offline
Registered User
  
 

Join Date: Apr 2007
Location: 44.21.48N 80.50.15W
Posts: 455
Is there a ".lastlogin" file in the users home directory. If this exists it has a size of 0 and its mtime is equal to the last login time.
So presumably:
find / -name .lastlogin -mtime +40

If it doesn't exist you could add "touch .lastlogin" to each user's .profile
and wait 40 days for the first occurence
  #4 (permalink)  
Old 04-25-2007
jim mcnamara jim mcnamara is offline Forum Staff  
...@...
  
 

Join Date: Feb 2004
Location: NM
Posts: 5,794
He may also want network logins...

Reading an accounting file is pretty much guaranteed to find everybody.
  #5 (permalink)  
Old 04-26-2007
ughosting ughosting is offline
Registered User
  
 

Join Date: Apr 2007
Posts: 3
Many thanks so far!!

Thanks for the suggestions!

Meanwhile I have come up with this!

It's not fast, but it does the job!

#!/usr/bin/ksh

#####
#
# Set up Global Variables
#
#####

MIN_DAYS=2
MAX_DAYS=90
DEF_GROUP="cpx"
DATECALC="<patch_to_datecalc>"

#####
#
# Preliminary Tests
#
#####

#
# Test for the correct parameters are passed or report Usage
#

case $# in

1)

NUM_DAYS=$1
SEARCH_GROUP=$DEF_GROUP
;;

2)

NUM_DAYS=$1
SEARCH_GROUP=$2
;;

*)

echo "Usage: $(basename $0) <num_days> [ <group> ]"
exit 1
;;

esac

#
# Test that the number of days passed is in range (and therefore a number)
#

if [ ${NUM_DAYS} -lt ${MIN_DAYS} ] || [ ${NUM_DAYS} -gt ${MAX_DAYS} ]
then

echo "<num_days> (${NUM_DAYS}) should be > ${MIN_DAYS} && < ${MAX_DAYS}"
exit 1

fi

#
# Test that the group name passed exists
#

grep -q "^${SEARCH_GROUP}" /etc/group

if [ $? = 1 ]
then

echo "<group> (${SEARCH_GROUP}) not found!"
exit 1

fi

#####
#
# Declare Local Functions and populate arrays
#
#####

dateformat () {

DATE_MONTH=$(echo "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec" | grep -n $2 | awk -F':' '{print$1}')

print "$5 ${DATE_MONTH} $3"
return 0
}

#####
#
# Start the program!!!
#
#####

SEARCH_NUM=$(grep "^${SEARCH_GROUP}" /etc/group | awk -F':' '{print$3}')

TODAY=$(dateformat $(date | awk '{print $1" "$2" "$3" "$4" "$6}'))

for i in $(grep "${SEARCH_NUM}" /etc/passwd | awk -F':' '{print$1}')
do

#
# Make sure that this user has logged in before trying to process them
#

grep -p "^${i}" /etc/security/lastlog | grep -q time_last_login

if [ $? = 0 ]
then

LOGGED_DATE=$(perl -le 'print scalar localtime shift' $(grep -p "^${i}" /etc/security/lastlog | grep time_last_login | awk '{print$3}'))
LOGGED_IN=$(dateformat ${LOGGED_DATE})

DIFF_DAYS=$(${DATECALC} -a ${TODAY} - ${LOGGED_IN})

if [ ${DIFF_DAYS} -ge ${NUM_DAYS} ]
then

typeset -L9 USER="${i}:"
typeset -R4 NUMBER=${DIFF_DAYS}
echo "${USER} ${NUMBER} days (${LOGGED_DATE})"

fi

fi

done


Of course, my AIX coding is a bit rubbish, so if anyone can see how to speed this up I would be interested.

I have used the datecalc script from this forum to perform the one date take away the other!!
  #6 (permalink)  
Old 04-26-2007
ughosting ughosting is offline
Registered User
  
 

Join Date: Apr 2007
Posts: 3
My Linux code for those interested

#!/bin/bash

NUM_DAYS="0"
TODAY_CODE=$(echo "$(date +%s) / 86400" | bc)

for i in $(cat /etc/passwd | awk -F':' '{print $1}')
do

last | grep ${i} > /dev/null 2>&1

if [ $? -eq 0 ]
then

DATE_TEXT=$(last | grep ${i} | head -1 | awk '{print $5" "$6}')
DATE_CODE=$(echo "$(date -d"${DATE_TEXT}" +%s) / 86400" | bc)
DIFF_DAYS=$(echo "${TODAY_CODE} - ${DATE_CODE}" | bc)

if [ ${DIFF_DAYS} -ge ${NUM_DAYS} ]
then

echo "${i} - ${DIFF_DAYS}"

fi

fi

done
Closed Thread

Bookmarks

Tags
linux, mtime, perl, perl shift, shift, shift perl

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On




All times are GMT -4. The time now is 02:28 AM.


Powered by: vBulletin, Copyright ©2000 - 2006, Jelsoft Enterprises Limited. Language Translations Powered by .
vBCredits v1.4 Copyright ©2007 - 2008, PixelFX Studios
The UNIX and Linux Forums Content Copyright ©1993-2009. All Rights Reserved.Ad Management by RedTyger

Content Relevant URLs by vBSEO 3.2.0