Bash script to remove user

14,528

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
Share:
14,528

Related videos on Youtube

Jake
Author by

Jake

Updated on September 18, 2022

Comments

  • Jake
    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:

    1. Does the user exist ?
    2. If user exists, backup /homedirectory for this user, remove username and place in /root/DeletedUsers
    3. If /root/DeletedUsers directory doesn't exist, create it.
    4. If any firewall rules exist for this user, email me the results for those rules and on which nodes.
    5. 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
      Ramesh about 10 years
      Change if [[ $firewall -ne 0 ]] to if [ $firewall -ne 0 ]. And similarly, change if [[ $doers -me 0 ]] to if [ $doers -ne 0 ].
    • Ramesh
      Ramesh about 10 years
      And 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
      Chad K about 10 years
      Also, change -count to -d in if [[! -count /Deleted_Users]]
    • celtschk
      celtschk about 10 years
      It 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 or deleted_users would have been a better name.
    • derobert
      derobert about 10 years
      I'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
      Jake about 10 years
      Creek, can you explain the reason for changing -count to -d ?
    • Jake
      Jake about 10 years
      Celtschk, yes thank you for your feedback. I did delete that extra quotation mark.
    • Jake
      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
      derobert about 10 years
      Instead of [[! -d /root/DeletedUsers]] you want ! [ -d /root/DeletedUsers ]. Or, honestly, if you use mkdir -p, that won't error if it already exists, so you can omit the test.
    • dawud
      dawud about 10 years
      You don't need a bash script. You need a central point of identity management and/or a configuration management system.
    • celtschk
      celtschk about 10 years
      In 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 or Ray6 (or both) in your current directory, the result will not be what you intended.
    • mikeserv
      mikeserv about 10 years
      I agree with @dawud - remotely locate /etc and /root at least - or regularly rsync them if necessary. Then when user management needs to occur you can just add a single script into init processes to mv user data as necessary but at least user permissions are centrally handled. Speaking of which - why cp and not mv?