The purpose of this script is to scan the /etc/passwd file one line at a time comparing the usernames to the usernames found in the /etc/mail/virtusertable file. When it comes across a name that is not in the virtusertable file then it will use sed to delete that line from the passwd file. Also, the script will ignore all "system" accounts and other accounts that have no e-mail alias in the virtusertable file. It will be used on a production mail server probably monthly to clean up a mess that gets left behind by other scripts. I really just want some input on this. If anyone sees anything obvious or sees something that could be done easier feel free to chime in. THIS SCRIPT HAS NOT BEEN TESTED!!! USE AT YOUR OWN RISK!! I CLAIM NO RESPONSIBILITY!! Feel free to use it though, if you think it works. I'm a bash scripting newb. I know a little C++ and as you can hopefully tell I've done some homework.

For your "BASEUSERS" variable, it might be a good idea to place the list in separate configuration file......The reason is not everyone will have the same system accounts in their particular passwd file......Some may be added by third party programs not included with their distro, or have system users shipped with the distro which is not on the list.......For example, Slackware 11 has over six default system user accounts not included in your base list.....

You can easily do this by cat'ing the list into the BASEUSERS variable:

This will shift the responsibility on to the sysadmin for making sure it is correct and up-to-date, but that should be okay since the system users accounts rarely get changed, and has the added benefit of you not having to guess all the different possible system accounts.....

---thegeekster

PS: To make it easy to begin with, you could have a base list of system users already set up in the config file, which can later be modified by the sysadmin.....

i worked out several little bugs today and actually did put the accounts in a seperate file... i knew that list would grow over time... btw, this list with the exception of two or three is a clean FreeBSD 6.1 install with apache, cucipop, vexira, and spamassassin

i did away with some of the loops using grep instead

the script (as it is on my harddrive right now) is working as it should except for one line... the line that actually deletes stuff... i'll get that sorted out tomorow and re-post the official working script

Last edited by Buggin on Tue Dec 12, 2006 10:32 pm, edited 2 times in total.

Looks like $n should actually be $N, sed being case-sensitive, and all ........Also, nothing is happening with sed, since you're suppressing the output (-n) and not having any way for sed to update the file..........And, the -e switch is not necesary if you enclose the entire "delete" action in quotes.......

Therefore, replace the -n -e switches with -i to tell sed to make the changes directly on the file (in place) and enclose the whole "delete" action in quotes, not just the variable ("${N}d").....You will need to use the curly braces around the variable name to let bash know that 'd' is not part of the name, or simply add a space in between ("$N d")....

Here's a much simpler approach in the for loop, but maybe not as obvious:

cp $PASSWORD_FILE $PASS_WRK #make a copy of passwd (passwd.wrk) file to manipulate and clean up;rm -f $PASS_LOG && touch $PASS_LOG # remove the old log and create an empty one in it's place

for NAME in $(cut -d: -f1 "$PASSWORD_FILE" ) #read names in from passwd.wrk filedo ## If NAME exists in either list, continue on to the next name: grep -q "\<$NAME\>" "$BASE_FILE" #grep virtusertable for $NAME if [ $? -eq 0 ]; then # If NAME exists, increment counter and let N++ && continue # skip the rest of the loop fi

For the root user check, I wasn't sure what you were trying to accomplish with the else keyword in the if statement, but it's not needed unless the 'echo' command was absolutely necessary for something.......

Instead of trying to empty the log file by reading nothing into it (cat /dev/null), why not simply delete it and create an empty log, instead.......

In the loop itself, all those if statements are also unnecessary (and a bit confusing to look at) if all you're doing is checking to see whether the names exist in either file.........If a name is found, you simply increment the counter and then issue the continue command to skip the rest of the loop and start on the next name in the list(s)......

And awk is not necessary and a bit of overkill in this instance..........cut would be more appropriate.......

When incrementing the N counter (N=$(($N+1))), it's much simpler and easier to do it with 'let': let N++.....Notice there is no dollar sign ($) in front of the variable name when using the let command...

And if you wanted to speed things up a bit, you can load both user files (base and virtuser) into memory by reading them into variables, using cat, and grepping from those variables.............Reading from memory is much faster than reading from disk for each and every loop:

the only reason i didn't use N++ is because it was giving me an error for some reason (Ubuntu box)

like i said i'm a scripting newb so i'm amazed it worked at all after only a couple days of trying

I'll test this today and make sure it's working ok and let you know.. thanks for all your help

PS I know i changed the variables to a different location than they actually should be... I wasn't about to test this on the actual production files until I knew it was working... now I have a couple hundred user names to scan through and check at random to make sure i didn't delete anything i shouldn't have... if all is well there this script is done.

Here it is. As far as I know it works. I've tested it somewhat randomly and no accounts that shouldn't have been removed were. Thanks for your help geekster. I used some of your code (particularly the sed line). I'm still a newb but I think I got one knockout under my belt now. I'm not sure if the && continue is useful the way I did the loop but I never tested it to see if it worked (the way I have it written at least). So there you go, if you use OptiGold or some other program that leaves trash behind in your passwd file here's one way to clear it out quick.

Code:

#!/bin/bash#cleanpasswdfile.sh##Goal: compare /etc/mail/virtusertable with /etc/passwd; find the entries missing from virtusertable that still exist in #passwd and remove from passwd file#

Hmm.......let is a bash builtin, and the fact it can't be found means something's broke with that bash installation....This is from the bash manpage, under the SHELL BUILTIN COMMANDS section towards the end:

Quote:

let arg [arg ...] Each arg is an arithmetic expression to be evaluated (see ARITHMETIC EVALUATION). If the last arg evaluates to 0, let returns 1; 0 is returned otherwise.

Look in your bash manpage to see if the above quote is there and, if it is, try reinstalling bash (the same version). If that doesn't work, try using a different version...........If it works with a different version, I suggest submitting a bug report to Ubuntu.........If it doesn't work or there's no reference in the bash manpage, then I suggest compiling it yourself or find a different distro........

i think i'll go check with ubuntuforums.org and see what i can find regarding this because i would like to have a properly working bash... most any script i write will be user on FreeBSD or FDC6 so it need to be compatible

You should be using bash, not dash.............dash is nothing more than an ash shell which was ported from NetBSD in '97, and doesn't have all the functionality of bash...............Debian uses dash (Debian ASH) for their installation root floppy since it's smaller and has fewer lib dependencies than bash.........Basically it's a '/bin/sh' replacement, not a 'bin/bash' substitute.........

yeah... the reconfigure asks if you want to load dash to /bin/sh because it is POSIX compliant and smaller and faster than bash

if you select no it loads bash instead

Code:

Ubuntu Configuration

â”Œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”¤ Configuring dash â”œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â” â”‚ â”‚ â”‚ Bash is the default /bin/sh on a Debian system. However, since our â”‚ â”‚ policy requires all shell scripts using /bin/sh to be POSIX compliant, â”‚ â”‚ any shell that conforms to POSIX can serve as /bin/sh. Since dash is â”‚ â”‚ POSIX compliant, it can be used as /bin/sh. You may wish to do this â”‚ â”‚ because dash is faster and smaller than bash. â”‚ â”‚ â”‚ â”‚ Install dash as /bin/sh? â”‚ â”‚ â”‚ â”‚ <Yes> <No> â”‚ â”‚ â”‚ â””â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”˜

i don't have a clue why they would want to load dash as default but if you select no everything will work as it should

I'm a bit confused here..........The shebang line in your script clearly says '/bin/bash', not 'bin/sh', so "bash" should be running the script........Is dash also replacing /bin/bash as well?.........I can see using dash, or ash (which I use), for the /bin/sh since it has less dependencies and is useful for a borked system..........

but, since you say everything works after saying 'no' to dash (just say no ), that leads me to believe dash is also replacing bash.......

Who is online

Users browsing this forum: No registered users and 8 guests

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum