LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   simple script (https://www.linuxquestions.org/questions/linux-newbie-8/simple-script-4175430562/)

karentc 10-04-2012 04:44 PM

simple script
 
I've used basic linux for a while, really basic. Now I need to write a simple script that will list all my users password status to a file.

I have a list of users (userlist.txt) and need to read that file and do chage -l user.

If you could tell me the steps are doing, it would help me to try other scripts. I'm using bash shell.

Thanks, Karen

porphyry5 10-04-2012 05:19 PM

Quote:

Originally Posted by karentc (Post 4797520)
I've used basic linux for a while, really basic. Now I need to write a simple script that will list all my users password status to a file.

I have a list of users (userlist.txt) and need to read that file and do chage -l user.

If you could tell me the steps are doing, it would help me to try other scripts. I'm using bash shell.

Thanks, Karen

If you enter 'chage' at the command line, it tells you this about its usage
Code:

~ $ chage
Usage: chage [options] [LOGIN]

Options:
  -d, --lastday LAST_DAY        set date of last password change to LAST_DAY
  -E, --expiredate EXPIRE_DATE  set account expiration date to EXPIRE_DATE
  -h, --help                    display this help message and exit
  -I, --inactive INACTIVE      set password inactive after expiration
                                to INACTIVE
  -l, --list                    show account aging information
  -m, --mindays MIN_DAYS        set minimum number of days before password
                                change to MIN_DAYS
  -M, --maxdays MAX_DAYS        set maximim number of days before password
                                change to MAX_DAYS
  -W, --warndays WARN_DAYS      set expiration warning days to WARN_DAYS

~ $

To do what you ask wouldn't need a formal script, just this command
Code:

chage -l < '/path/to/userlist.txt'
where 'chage -l' shows account aging information
< means following string is your input file path
Quotes on the file path are necessary only if it includes embedded whitespace (spaces, tabs, newlines), and may be single or double in this case
/path/to/ is the path to the directory containing the file of user names, not needed if that is the current directory
And it would show out put like this
Code:

~ $ chage -l g     
Last password change                                    : Jun 04, 2012
Password expires                                        : never
Password inactive                                      : never
Account expires                                        : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 99999
Number of days of warning before password expires      : 7
~ $

for each user name in userlist.txt (g is my user name)
To send the output to a file instead of printing it on the console, instead use the command as
Code:

chage -l < '/path/to/userlist.txt' > '/path/to/chageoutput.txt'

karentc 10-04-2012 05:35 PM

I did as you suggested. But received the following results. Maybe I'm missing something?
# chage -l < '/tmp/userlist.txt > '/tmp/output.txt'
>
>
>

suicidaleggroll 10-04-2012 05:37 PM

You're missing a single quote after userlist.txt

The > prompt is the shell waiting for you to finish the command. It has only encountered three quotes so far, it's expecting a fourth. You can use Ctrl+C to cancel the command, then you can fix it and run it again.

karentc 10-04-2012 05:41 PM

Sorry, missed that, but this is what I had when I first tried feeding the file in and then outputting.

chage -l < '/users/userlist.txt' > '/tmp/results.txt'
Usage: chage [-l] [-m min_days] [-M max_days] [-W warn]
[-I inactive] [-E expire] [-d last_day] user
#

suicidaleggroll 10-04-2012 05:45 PM

Yeah it looks like chage doesn't like that syntax. Try this
Code:

while read user; do echo $user; chage -l $user; done < /users/userlist.txt > /tmp/results.txt
Or in script form:
Code:

while read user; do
  echo $user
  chage -l $user
done < /users/userlist.txt > /tmp/results.txt


karentc 10-04-2012 05:57 PM

This is giving the results that prompted me to post this question. But I do appreciate the help. The data in the results.txt file is the same listing that is in the userlist.txt. So it's just outputting the file it read.

# while read user; do echo $user; chage -l $user; done < /users/userlist.txt > /tmp/results.txt
chage: unknown user: abennet
chage: unknown user: gwhite
chage: unknown user: jallan
chage: unknown user: csmith
#

suicidaleggroll 10-04-2012 06:13 PM

It's just outputting the same file it read because apparently none of the users exist on the system, so all you get is the "echo $user" with blank output from the chage -l.

This is how the output should look, if the users actually exist:
Code:

# cat users.txt
user1
user2
user3
# while read user; do echo $user; chage -l $user; done < users.txt > results.txt
# cat results.txt
user1
Last password change                                        : Mar 01, 2010
Password expires                                        : never
Password inactive                                        : never
Account expires                                                : never
Minimum number of days between password change                : 0
Maximum number of days between password change                : 99999
Number of days of warning before password expires        : 7
user2
Last password change                                        : Jul 02, 2012
Password expires                                        : never
Password inactive                                        : never
Account expires                                                : never
Minimum number of days between password change                : 0
Maximum number of days between password change                : 99999
Number of days of warning before password expires        : 7
user3
Last password change                                        : Apr 03, 2012
Password expires                                        : never
Password inactive                                        : never
Account expires                                                : never
Minimum number of days between password change                : 0
Maximum number of days between password change                : 99999
Number of days of warning before password expires        : 7
#


karentc 10-04-2012 06:25 PM

I must be doing something incorrectly. I have over 150 users, all exist in the /users/ directory. If I manually do chage -l user1, I get the correct output. But if user1 is in the list /users/userlist.txt, it doesn't output anything, except the name of the user. I've checked for spaces, and there aren't any. I could see one or two typos' in the list, but not all of them.

cbtshare 10-04-2012 08:09 PM

try

Quote:

#!/bin/bash

cat user.txt |
while read user;
do

echo Result For user $user Below >>output.txt
chage -l $user >> output.txt
done


suicidaleggroll 10-04-2012 09:33 PM

Quote:

Originally Posted by karentc (Post 4797593)
I must be doing something incorrectly. I have over 150 users, all exist in the /users/ directory. If I manually do chage -l user1, I get the correct output. But if user1 is in the list /users/userlist.txt, it doesn't output anything, except the name of the user. I've checked for spaces, and there aren't any. I could see one or two typos' in the list, but not all of them.

How did you make the list? Maybe it has some weird EOL terminators that are making their way into the chage -l call?

catkin 10-05-2012 02:38 AM

To see if the user names from the file are as expected, what is the output from
Code:

while read -r user; do echo ">$user<"; done < /users/userlist.txt

porphyry5 10-05-2012 10:12 AM

Try this approach
Code:

~ $ cat fred.txt
g
Root
q
~ $ mapfile < fred.txt x
~ $ y=${#x[@]}
~ $ for ((i=0; i<y; i++)); do chage -l ${x[$i]}; done
Last password change                                    : Jun 04, 2012
Password expires                                        : never
Password inactive                                      : never
Account expires                                        : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 99999
Number of days of warning before password expires      : 7
chage: user 'Root' does not exist in /etc/passwd
chage: user 'q' does not exist in /etc/passwd
~ $

mapfile is a bash internal that creates an array (x) from an input file (fred.txt) using an entire line as the content of each cell. Usually it is used with a '-t' option which omits the newline character from each line when building the array. Without '-t' each cell includes the newline, and I believe it was the lack of this which caused the failure of other methods.
y=${#x[@]} gets the number of cells in array x
The 'for' loop delivers the content of each cell in array x to chage, including the linebreak. That is, it simulates exactly what happens when you enter the username at the console, and press Return.

Mine is a single user machine, so /etc/passwd has only my user entry in it, hence the rejection of Root and q

Following is the 'for' loop rewritten to send chage's output to a file, o.txt. >> is used because we need each user output appended to the file
Code:

~ $ for ((i=0; i<y; i++)); do chage -l ${x[$i]} >> o.txt; done
chage: user 'Root' does not exist in /etc/passwd
chage: user 'q' does not exist in /etc/passwd
~ $ cat o.txt
Last password change                                    : Jun 04, 2012
Password expires                                        : never
Password inactive                                      : never
Account expires                                        : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 99999
Number of days of warning before password expires      : 7
~ $

Apparently the non-existent users are being rejected by bash and never presented to chage

And as chage doesn't bother to tell you the user name its dealing with, you might want to make the 'for' loop something like
Code:

for ((i=0; i<y; i++)); do chage -l ${x[$i]} >> o.txt; echo "Above Entry for User ${x[$i]}"; done

karentc 10-05-2012 10:13 AM

I copied and pasted your exact line and received
<abennet
<gwhite
<jallan
<csmith

It seems so simple, which is why I'm so stumped. I feel like I'm just missing some obvious typo.

karentc 10-05-2012 10:25 AM

Hmmm, it is a bash shell, but no mapfile found. I'm running Red Hat Enterprise Linux ES release 4 (Nahant Update 7)

While this hasn't solved my problem, I really appreciate the help and this has given me a lot more to work with. Thanks.


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