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 |
Quote:
Code:
~ $ chage Code:
chage -l < '/path/to/userlist.txt' < 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 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' |
I did as you suggested. But received the following results. Maybe I'm missing something?
# chage -l < '/tmp/userlist.txt > '/tmp/output.txt' > > > |
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. |
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 # |
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 Code:
while read user; do |
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 # |
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 |
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.
|
try
Quote:
|
Quote:
|
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 |
Try this approach
Code:
~ $ cat fred.txt 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 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 |
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. |
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. |
Quote:
The output of that command should have looked like this: Code:
>abennet< |
I don't know when mapfile was added to bash, I'm using this version
Code:
~/Documents $ bash --version Code:
~ $ IFS=$'\x0A' x=($(cat < fred.txt)) creates the array x you still need to set y as before to the number of items in x, but as I'm using the same terminal its still there for me. IFS=$'\x20'$'\x09'$'\x0A' resets IFS to its default values, any one of space, tab or newline. Bash is a delightfully arcane language. If you need a tutorial for it, try http://mywiki.wooledge.org/BashGuide or http://www.grymoire.com/Unix/Sh.html The second one is a subset of bash, but as a single page it is easy to download and use offline, as it only references itself. |
I think these suggestions are getting needlessly complex. The problem is the formatting in his file, as evidenced by post #14. More intricate and complicated ways of calling chage which still depend on newline-separated fields in the file aren't going to help matters, because his file is apparently not newline-separated...at least not properly.
We need to go back to the source - how was the file created, and why does it not look like what any of these scripts expect? If that can be resolved, I think almost any of the solutions already posted in this thread will work fine. Just my thoughts on the matter... |
I tried:
for ((i=0; i<y; i++)); do chage -l ${x[$i]} >> test.txt; echo "Above Entry for User ${x[$i]}"; done which produced nothing. Not even an output file. Again I appreciate your help. |
Quote:
Code:
~ $ bpe fred.txt |
so bpe doesn't exist on my system. The file was created from an ls -l > userlist.txt and then opened in excel, deleted what I didn't want and saved as a text file. Once transferred back, I checked it with vi.
|
Quote:
Code:
:%!xxd " enters hex mode |
Quote:
In the mean time, try running "dos2unix userlist.txt", and then re-run the test you did in step 14. |
Thanks everyone. I found a post by Ricky_ds that came at the problem from a different angle and I ran that to an output file and I have everything I need. Again I appreciate all your time. Still not sure why this wouldn't work, but I have what I need. Just changed the location of the users and it's all good.
#!/bin/bash formatDate() { date +%d"."%m"."%Y -d " $1 day" } padr() { string="$1................................................" echo "$string" | cut -c1-$2 } length() { length=`echo "$@" | wc -c | cut -c1-8` length=$(( $length -1 )) echo $length } padl() { string="................................................$1" length=`length "$string"` echo "$string" | cut -c`expr $length - $2`-$length } if [ "$#" = "0" ]; then echo echo "List of user accounts with password information" echo "===============================================" echo `date` echo echo "Legend: M=Minimum password age W=Warning in days before exp" echo " Dis=Account Disabled" echo "------------------------------------------------------------------------------------------" echo "Username |Full name |UID |LastChange|M|Max |W|Passwd Exp|Dis |Acct Exp " echo "----------|-------------------------|-----|----------|-|-----|-|----------|----|----------" fi sort /etc/passwd |grep ":/home/" | awk -F":" '{print}' |\ while read line ; do name=`echo -e $line | awk -F: '{print$1}'` uname=`cat /etc/shadow | grep -r "^$name:" | awk -F":" '{print}'` thisuser=`echo -e $uname | awk -F: '{print$1}'` if [ "$#" = "1" ] && [ "$1" = "$thisuser" ] || [ "$#" = "0" ]; then a=`echo -e $uname | awk -F: '{print$3}'` b=`echo -e $uname | awk -F: '{print$4}'` c=`echo -e $uname | awk -F: '{print$5}'` d=`echo -e $uname | awk -F: '{print$6}'` e=`echo -e $uname | awk -F: '{print$7}'` f=`echo -e $uname | awk -F: '{print$8}'` uid=`echo -e $line | awk -F: '{print$3}'` fullname=`echo -e $line | awk -F: '{print$5}'` now=$(( ($(date +%s) / 86400) )) pass=$(( $now - $a )) last=`formatDate -$pass` if test "$f" != "" ; then next=$(( $f - $now )) exp=`formatDate $next` else exp=`echo NEVER` fi pexpt=$(( $a + $c )) pexpt=$(( $pexpt - $now )) pexp=`formatDate $pexpt` if [ "$#" = "1" ]; then echo echo "===Information for user $name===" echo "Full name: $fullname" echo "User ID: $uid" echo "Password last changed: $last" echo "Minumum password age: $b" echo "Maximum password age: $c" echo "Password warning age: $d" echo "Password expires on: $pexp" if test "$e" != "" ; then echo "The account will be disabled *$e* days after expiration" fi echo "The account expires on: $exp" echo else name=`padr $name 10` c=`padl $c 4` if test "$e" = "" ; then e="." fi e=`padl $e 3` exp=`padl $exp 9` fullname=`padr "$fullname" 25` uid=`padl $uid 4` echo "$name|$fullname|$uid|$last|$b|$c|$d|$pexp|$e|$exp" fi fi done |
As per suicidaleggroll; that was exactly my reaction as well
|
All times are GMT -5. The time now is 08:37 AM. |