Bash script to remove user
Solution 1
I would suggest you use getent
to check for the existence of an user. This script should get you going.
##Check if the user exists using getent command
user_exists=$(getent passwd $1)
##If the user doesn't exist, we need not perform the backup.
if [ -z "$user_exists" ]
then
echo "User $1 does not exist"
else
cd /root
#Incorporating derobert's suggestion here.
mkdir -p "DeletedUsers"
##Use tar or rsync to do the backup as cp will be inefficient.
tar czvf "$1".tar.gz /home/"$1"
firewall=$(grep -c "192.168.5.5" /etc/sysconfig/iptables)
doers=$(egrep -c "$1" /etc/sudoers)
userdel -rf "$1"
if [ $firewall -ne 0 ]
then
mail -s "$firewallrulesexist" emailaddress < /dev/null
fi
if [ $doers -ne 0 ]
then
sed ^"$1" /#/i
fi
fi
You can call the script as ./deal ray[4]
and then if you need to run for another user you can call it using ./deal ray[6]
. I have not tested the script in my system, but this should help you out as in case if you need to delete any other user in future, you need not modify the script but rather call the script with the username as an argument.
EDIT
As per derobert's suggestion, you can omit directory testing if you use -p
flag.
Solution 2
If Ray[46]
is assuredly unique, pretty much every test in your script is redundant.
printf %s\\n 123 456 | sed '/2/s///'
#OUTPUT#
13
456
The above will scan its input for any line containing the /addressed/
string 2
, and, if found, will change only that line to contain everything but the addressed string. The following simply deletes only addressed lines:
printf %s\\n 123 456 | sed '/2/d'
#OUTPUT#
456
So grep
then sed
is not necessary. True, grep
is faster than sed
, but in the time it takes to invoke grep
and [test]
its output then invoke sed
, sed
would likely already have finished clearing all concerned files of the offending string.
Then again, if you do want to grep
then sed
for whatever reason, the following would be much more to the point:
remove=string ; for f in $(grep -l "$remove" $file_list) ; do
printf %s "$(sed "/$remove/s///" "$f")" >"$f" ; done
Or with GNU sed
:
sed -i "/$remove/s///" $(grep -l "$remove" $file_list)
And as mentioned above, mkdir -p
makes a target directory only if necessary, so this should suffice:
mkdir -p /root/DeletedUsers ; mv /home/$string "$_"
You could even get a log of it all to review exactly what was done on only those machines something occurred:
#ensure $tgt dir exists
mkdir -p ${tgt=/root/DeletedUsers}
#handles Ray4 and Ray6 cases on a single machine
for remove in /home/Ray[46] ; do hostname #print hostname
#nothing happens unless user's $HOME exists
cd "$remove" 2>/dev/null || {
echo "No $remove found here."
break
}
#get out of user's $HOME and mv it
cd - ; mv -v "$remove" "$tgt"
#strip $remove to only username then userdel it
remove=${remove##*/}
userdel -rf $remove
#if $remove in /etc/sudoers comment file's line and and copy change to stderr
sed -nei "/$remove/{!p;b};s/^/#/p" /etc/sudoers \
-ne "s/^/sudoers change: /w /dev/stderr"
#print all iptables lines containing string $remove
grep "$remove" /etc/sys/config/iptables |
#for each rule found append a noticeable marker line
sed "a--- "$(hostname)"firewall found"
#finish for statement and pipe all to remote cat to append to log
done 2>&1 | ssh you@host 'cat >>~/Raydel.log'
That above assumes your target user has a $HOME
in /home
named for the user's username. If the assumption is correct, it only takes action on any machine on which the target user's username is registered.
To do the same without grep
you can leave tee
out as well. Just change the sed
line to:
for f in $file_list ; do
sed -ni "/$remove/{h;s///};p;\$!b;x;/$remove/s|.*|$f|w /dev/stderr" "$f"
done
That will overwrite sed's
holdspace with each new line sed
finds containing the string "$remove"
. When sed's
through scanning and gets to the last line it switches to the holdspace, and, if it finds any references to $remove
it writes the filename to stderr
.
If you run a script like the one I wrote above from your own machine and you ssh
out to all of the targets then you don't have to open an ssh
connection from each of them back to your own machine - you're already there. You could remove the last |pipe
and everything following it and do this instead:
script=$(cat <<\SCRIPT
#body of the script I wrote above less the |pipe and all that followed
SCRIPT
)
for host in $hosts ; do ssh you@$host "$script" ; done >>~/Raydel.log
Related videos on Youtube
Jake
Updated on September 18, 2022Comments
-
Jake over 1 year
I need to create a Bash script to remove a user.
We use RHEL version 4, 5, & 6.
Lets say usernames are Ray4 & Ray6 & the script name is deal.
Specific tasks for this script are:- Does the user exist ?
- If user exists, backup /homedirectory for this user, remove username and place in /root/DeletedUsers
- If /root/DeletedUsers directory doesn't exist, create it.
- If any firewall rules exist for this user, email me the results for those rules and on which nodes.
- If this user exists in sudoers, don't delete, but comment out.
This is what I have so far. I want to make sure this works, before I run it in RHN Satellite. After making the suggested changes. Here are the new errors I am getting now.
[root@localhost bin]# ./deal ./deal: line 7: [[!: command not found Usage: userdel [options] LOGIN Options: -f, --force force removal of files, even if not owned by user -h, --help display this help message and exit -r, --remove remove home directory and mail spool -Z, --selinux-user remove SELinux user from SELinux user mapping Usage: userdel [options] LOGIN Options: -f, --force force removal of files, even if not owned by user -h, --help display this help message and exit -r, --remove remove home directory and mail spool -Z, --selinux-user remove SELinux user from SELinux user mapping Null message body; hope that's ok ./deal: line 22: [: -me: binary operator expected This is source code:
[root@localhost bin]# cat -n deal 1 #!/bin/bash 2 3 count=$(egrep -c Ray[46] /etc/passwd) 4 firewall=$(grep -c "192.168.5.5" /etc/sysconfig/iptables) 5 doers=$(egrep -c Ray[46] /etc/sudoers) 6 7 if [[! -d /root/DeletedUsers]] 8 then mkdir /root/DeletedUsers 9 10 fi 11 12 cp -Rf /home/Ray[46] /root/DeletedUsers 13 userdel -rf Ray [4] 14 userdel -rf Ray [6] 15 16 if [ $firewall -ne 0 ] 17 18 then mail -s "$firewallrulesexist" emailaddress < /dev/null 19 20 fi 21 22 if [ $doers -me 0 ] 23 then sed ^Ray[46] /#/i 24 25 EOF 26 fi
-
Ramesh about 10 yearsChange
if [[ $firewall -ne 0 ]]
toif [ $firewall -ne 0 ]
. And similarly, changeif [[ $doers -me 0 ]]
toif [ $doers -ne 0 ]
. -
Ramesh about 10 yearsAnd where are you creating the
DELETED USERS
directory? If it is under current directory, then no need of` and also use
"` to create the directory. Something like,mkdir "DELETED USERS"
. -
Chad K about 10 yearsAlso, change
-count
to-d
inif [[! -count /Deleted_Users]]
-
celtschk about 10 yearsIt is generally a bad idea (and an invitation to hard to find bugs) to have spaces in directory names, especially if you plan to access them by shell commands and/or shell scripts. Any of
DeletedUsers
,deleted-users
ordeleted_users
would have been a better name. -
derobert about 10 yearsI've tried to add line numbers so that people can see which lines the errors are occurring on, but it seems something has gone wrong... Did a line breaks get messed up in the copy & paste to SE? Anyway, I changed the line numbers in the errors to match. Also, you don't have an error for it, so I presume the first line actually is
#!/bin/bash
—that is, the#
is not missing? -
Jake about 10 yearsCreek, can you explain the reason for changing -count to -d ?
-
Jake about 10 yearsCeltschk, yes thank you for your feedback. I did delete that extra quotation mark.
-
Jake about 10 years[root@localhost bin]# ./deal ./deal: line 7: [[!: command not found cp: target `/RemovedUsers' is not a directory Usage: userdel [options] LOGIN Null message body; hope that's ok ./deal: line 22: [: -me: binary operator expected
-
derobert about 10 yearsInstead of
[[! -d /root/DeletedUsers]]
you want! [ -d /root/DeletedUsers ]
. Or, honestly, if you usemkdir -p
, that won't error if it already exists, so you can omit the test. -
dawud about 10 yearsYou don't need a bash script. You need a central point of identity management and/or a configuration management system.
-
celtschk about 10 yearsIn line 3 and line 5, you definitely want to protect the regular expression from the shell. Otherwise if you happen to have a file named
Ray4
orRay6
(or both) in your current directory, the result will not be what you intended. -
mikeserv about 10 yearsI agree with @dawud - remotely locate
/etc
and/root
at least - or regularlyrsync
them if necessary. Then when user management needs to occur you can just add a single script into init processes tomv
user data as necessary but at least user permissions are centrally handled. Speaking of which - whycp
and notmv
?