LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - General (https://www.linuxquestions.org/questions/linux-general-1/)
-   -   /etc/profile script (https://www.linuxquestions.org/questions/linux-general-1/etc-profile-script-555998/)

sachinh 05-23-2007 03:16 AM

/etc/profile script
 
Our reqt is , whenever any user logs in to the system , a script should get executed. This script will create a new file in respective Home Dir.
I tried writing such script and put it under /etc/profile.d/test { We have RHEL 4.0 }
But whenever the user logs in it gives error as

touch: cannot touch `.last_date': Permission denied

The script we are trying to execute is having following permissions.
-rwxr-xr-x 1 root root 187 /etc/profile.d/test

Please suggest !!!!!!

druuna 05-23-2007 03:19 AM

Hi,

What is the content of the test script? Looks like it's one (?) of the commands in there that's causing the problem/error.

sachinh 05-23-2007 03:30 AM

Quote:

Originally Posted by druuna
Hi,

What is the content of the test script? Looks like it's one (?) of the commands in there that's causing the problem/error.

Script :- I have put it under /etc/profile.d/

echo $HOME
if [ -f $HOME/.neverlogin ]; then
rm $HOME/.neverlogin
else
touch $HOME/.lastlogin_date
date >> $HOME/.lastlogin_date
fi

druuna 05-23-2007 06:51 AM

Hi,

The given info looks ok.

What are the permissions/owner/group of the .lastlogin_date file?

jschiwal 05-23-2007 07:31 AM

You could use "lastlog -u username" to obtain the last login of a user. To lock out an account, you can use "passwd -l username" instead of file in their home directory.

sachinh 05-23-2007 09:26 PM

Quote:

Originally Posted by jschiwal
You could use "lastlog -u username" to obtain the last login of a user. To lock out an account, you can use "passwd -l username" instead of file in their home directory.


We are little reluctant to use lastlog as it does not consider YEAR . (Thats what we think) .

Another thing is that , how can we get a user's home directory in a shell.

E.g.

for i in `cat UserList`
do
HomeDir= {This variable should get the value of the respective User's
Home Directory in every iteration of "i" }
echo $HomeDir
done

druuna 05-24-2007 01:49 AM

Hi,

Quote:

Another thing is that , how can we get a user's home directory in a shell.

E.g.

for i in `cat UserList`
do
HomeDir= {This variable should get the value of the respective User's
Home Directory in every iteration of "i" }
echo $HomeDir
done
Something like this will give you the homedir of a specific user:

HomeDir="`awk -F: -v i=$i '$1 ~ i { print $6}' /etc/passwd`"

Hope this helps.

BTW: Did you solve your original problem?

jschiwal 05-24-2007 02:29 AM

Quote:

Originally Posted by sachinh
We are little reluctant to use lastlog as it does not consider YEAR . (Thats what we think) .

Another thing is that , how can we get a user's home directory in a shell.

E.g.

for i in `cat UserList`
do
HomeDir= {This variable should get the value of the respective User's
Home Directory in every iteration of "i" }
echo $HomeDir
done

The home directory is contained in a field of /etc/passwd. However, if you use the default setup, you probably have a directory under /home that has the same name as the user.

So you could have a loop like:
Code:

for dir in /home/*; do

....

done

Also, keep in mind that /etc/passwd has system users as well. The range of UIDs used for regular users differs for different distros. Mandriva & Fedora Core start at 500, whereas SuSE starts at 1000. Anyway, you will need to examine the UID to determine if the user in /etc/passwd is a regular user. The bottom and top range may be defined in /etc/login.defs.

Given the tests you need to perform, you may want to produce a temp file containing the usernames and then use that list as items in a loop.
Code:

passwords=$(cat /etc/passwd)  # I'm always looking for excuses to use arrays in bash
for (( entry=0; entry<${#passwords[@]}; entry++ )); do
  uid=$(echo ${passwords[$entry]} | cut -d':' -f1)
  if [ $uid -ge 500 -a $uid -lt 2000 ]; then  # regular users have uids between 500 and 2000 inclusively.
      echo $(echo ${passwords[$entry]} | cut -d':' -f3) >reguserlist
  fi  # add user to list if in range.
done

for username in $(cat reguserlist);do

...

done
rm reguserlist

The normal lastlog entry does have the year:
Code:

Username        Port    From            Latest
root            tty1                      Thu Jan 25 15:23:50 +0530 2007
daemon                                    **Never logged in**
bin                                        **Never logged in**
sys                                        **Never logged in**
sync                                      **Never logged in**
vivek            tty1                      Sat Jan 27 22:10:36 +0530 2007
pdnsd                                      **Never logged in**
sshd                                      **Never logged in**
messagebus                                **Never logged in**
bind                                      **Never logged in**

I'm not at my linux machine to check the output of "lastlog -u username".

A user would be able to delete a ~/.last_date file before logging off.
Or even use the touch command using a date years in the future.
If you really don't want to use lastlog, you could list the access time for ~/.profile or ~/.bashrc, however, the user might be using another shell.

sachinh 05-24-2007 09:23 PM

Quote:

Originally Posted by druuna
Hi,

The given info looks ok.

What are the permissions/owner/group of the .lastlogin_date file?


Hi Druuna,

Yes the problem with /etc/profile got resolved . How ?? Initially we thought just placing the script under /etc/profile.d would itself execute the script whenevera user logs in. But it didnt work ( Dont know whether it should be working this way ) .
So added an entry in /etc/profile file to execute the script. It worked !!
Last but not the least , we can place this script under any directory , it need not be /etc/profile.d.

Anyways ....thanks to you for showing concern!!!! Will meet sooon :)

sachinh 05-24-2007 09:32 PM

[QUOTE=jschiwal]The home directory is contained in a field of /etc/passwd. However, if you use the default setup, you probably have a directory under /home that has the same name as the user.

So you could have a loop like:
Code:

for dir in /home/*; do

....

done

Yes you are correct. But we didnt want to take any chances as few of our systems are having users with non-default( other than /home) home directories. But thanks for pointing it out.

Quote:

Originally Posted by jschiwal
Also, keep in mind that /etc/passwd has system users as well. The range of UIDs used for regular users differs for different distros. Mandriva & Fedora Core start at 500, whereas SuSE starts at 1000. Anyway, you will need to examine the UID to determine if the user in /etc/passwd is a regular user. The bottom and top range may be defined in /etc/login.defs.

Given the tests you need to perform, you may want to produce a temp file containing the usernames and then use that list as items in a loop.
Code:

passwords=$(cat /etc/passwd)  # I'm always looking for excuses to use arrays in bash
for (( entry=0; entry<${#passwords[@]}; entry++ )); do
  uid=$(echo ${passwords[$entry]} | cut -d':' -f1)
  if [ $uid -ge 500 -a $uid -lt 2000 ]; then  # regular users have uids between 500 and 2000 inclusively.
      echo $(echo ${passwords[$entry]} | cut -d':' -f3) >reguserlist
  fi  # add user to list if in range.
done

for username in $(cat reguserlist);do

...

done
rm reguserlist


We wrote a different code to find out regular user list but yes the above code is also worth.
Will definately give it a shot !!!! Thanks again :)


Quote:

Originally Posted by jschiwal
The normal lastlog entry does have the year:
Code:

Username        Port    From            Latest
root            tty1                      Thu Jan 25 15:23:50 +0530 2007
daemon                                    **Never logged in**
bin                                        **Never logged in**
sys                                        **Never logged in**
sync                                      **Never logged in**
vivek            tty1                      Sat Jan 27 22:10:36 +0530 2007
pdnsd                                      **Never logged in**
sshd                                      **Never logged in**
messagebus                                **Never logged in**
bind                                      **Never logged in**

I'm not at my linux machine to check the output of "lastlog -u username".

Yes even on Linux we get year field. But we are trying to manipulate things based on whether User has logged into the system for more than 90 Days or not. So we decided not to rely on to lastlog.




Quote:

Originally Posted by jschiwal
A user would be able to delete a ~/.last_date file before logging off.
Or even use the touch command using a date years in the future.
If you really don't want to use lastlog, you could list the access time for ~/.profile or ~/.bashrc, however, the user might be using another shell.


The above points you mentioned are really interesting and we have to give it a thought before we finalise things.
Maybe we would think of creating .last_date file for each user in a different location where regular users dont have access to. Will it help??

Listing the access time for ~/.profile is also a nice way . Will think over it and see if it fits our requirement.

Last but not the least .... Thanks a TON for your valuable advise. Its people like you and Druuna that make this Life more beautiful !!!!!!!!!!!!! :)

frob23 05-24-2007 09:50 PM

Now comes the issue of users who change their default shell. People who prefer something other than a bourne style shell are almost certain to change that as one of the first things when they get access to the system. I'll freely admit that it's something I do. So after 90 days, regardless of how often I log in, it looks like I have only been on once.

Frankly, using login scripts to monitor this is too much of a kluge to be reliable and is likely to be easily subverted by smart users who feel like it inconveniences them.

sachinh 05-24-2007 09:56 PM

Quote:

Originally Posted by frob23
Now comes the issue of users who change their default shell. People who prefer something other than a bourne style shell are almost certain to change that as one of the first things when they get access to the system. I'll freely admit that it's something I do. So after 90 days, regardless of how often I log in, it looks like I have only been on once.

Frankly, using login scripts to monitor this is too much of a kluge to be reliable and is likely to be easily subverted by smart users who feel like it inconveniences them.

Hi ,
Listed nice points...... but then its without any suggestions ....so ..now waiting for it !!

frob23 05-24-2007 10:01 PM

Personally, you have some good suggestions... but let me tell you how to make them work.

Don't toss out the lastlog suggestion above... but if you feel it is not adequate then supplement it. Write a shell script which will take the output of lastlog, grab only the last day, and will parse them into a sorted file.

Have that same script produce a list of users who have not logged in for 90 days and output that list to a file somewhere.

Have this list called, daily, from cron. It will automate the whole thing... actually you can go even further... and have it email the users or deactivate their accounts automatically if they haven't been on for 90 days. Just be sure (if you automate it) to not deactivate/remove the root account.

frob23 05-24-2007 10:50 PM

Code:

#!/bin/sh
OLDMASK=`umask`
TIMESTAMP=`date +%s`
FILENAME=/tmp/accounting
TMPFILE=/tmp/accounting.new
EXPIRED=/tmp/expired.accounts

# This is the number of seconds until the account is out of date:
# 7776000 = 90 days
SECONDS=7776000

umask 077

if [ ! -f ${FILENAME} ]; then
        touch ${FILENAME}
fi

#lastlog | awk '{print $1}' | while read LINE
lastlog | grep "`date | awk '{print $2, $3".*"$6}'`" | awk '{print $1}' | while read LINE
do
        awk -v time=${TIMESTAMP} -v user="${LINE}" 'BEGIN{found=0}{if($2 == user){$1=time;found=1};print $0}END{if(found!=1){print time" "user}}' ${FILENAME} > ${TMPFILE}
        mv ${TMPFILE} ${FILENAME}
done

sort -n ${FILENAME} > ${TMPFILE}
mv ${TMPFILE} ${FILENAME}

awk -v time=${TIMESTAMP} -v secs=${SECONDS} 'BEGIN{old=time-secs}{if($1<=old)print $2}' ${FILENAME} >> ${EXPIRED}

umask ${OLDMASK}

Here is something I just threw together... as an example... obviously, this is not what I would use in production. You would want those temp files somewhere else (probably under a protected directory only readable by the user running the program). This program is also simplified a lot (it could be more complex but I didn't see the need).

The people who have not logged in for 90 days would be put in /tmp/expired in this program. Also... you would need to modify this for the initial population of /tmp/accounting or else it will only catch those who don't use the system for 90 days after using it once this system is in place. It doesn't catch those who never log in... so that's another matter.

And so on. You could have the expired file mailed... oh, and one more thing... the current version doesn't remove the expired accounts from /tmp/accounts. That would require a trivial change (look at the last awk line) and is left as an exercise for the reader.

More could be done with this framework... but it gives an idea. And it also is outside the control of pesky users... and their evil ways. ;)

sachinh 05-24-2007 11:06 PM

Quote:

Originally Posted by frob23
Code:

#!/bin/sh
OLDMASK=`umask`
TIMESTAMP=`date +%s`
FILENAME=/tmp/accounting
TMPFILE=/tmp/accounting.new
EXPIRED=/tmp/expired.accounts

# This is the number of seconds until the account is out of date:
# 7776000 = 90 days
SECONDS=7776000

umask 077

if [ ! -f ${FILENAME} ]; then
        touch ${FILENAME}
fi

#lastlog | awk '{print $1}' | while read LINE
lastlog | grep "`date | awk '{print $2, $3".*"$6}'`" | awk '{print $1}' | while read LINE
do
        awk -v time=${TIMESTAMP} -v user="${LINE}" 'BEGIN{found=0}{if($2 == user){$1=time;found=1};print $0}END{if(found!=1){print time" "user}}' ${FILENAME} > ${TMPFILE}
        mv ${TMPFILE} ${FILENAME}
done

sort -n ${FILENAME} > ${TMPFILE}
mv ${TMPFILE} ${FILENAME}

awk -v time=${TIMESTAMP} -v secs=${SECONDS} 'BEGIN{old=time-secs}{if($1<=old)print $2}' ${FILENAME} >> ${EXPIRED}

umask ${OLDMASK}

Here is something I just threw together... as an example... obviously, this is not what I would use in production. You would want those temp files somewhere else (probably under a protected directory only readable by the user running the program). This program is also simplified a lot (it could be more complex but I didn't see the need).

The people who have not logged in for 90 days would be put in /tmp/expired in this program. Also... you would need to modify this for the initial population of /tmp/accounting or else it will only catch those who don't use the system for 90 days after using it once this system is in place. It doesn't catch those who never log in... so that's another matter.

And so on. You could have the expired file mailed... oh, and one more thing... the current version doesn't remove the expired accounts from /tmp/accounts. That would require a trivial change (look at the last awk line) and is left as an exercise for the reader.

More could be done with this framework... but it gives an idea. And it also is outside the control of pesky users... and their evil ways. ;)


Thanks a ton..This thread is really rising HIGH now. Cant wait to work on the above script. Wait for my feedback on above script.


All times are GMT -5. The time now is 07:45 AM.