사용자를 삭제하는 Bash 스크립트

사용자를 삭제하는 Bash 스크립트

사용자를 삭제하려면 Bash 스크립트를 만들어야 합니다.
우리는 RHEL 버전 4, 5, 6을 사용합니다.
사용자 이름이 Ray4 및 Ray6이고 스크립트 이름이 deal이라고 가정합니다.
이 스크립트의 특정 작업은 다음과 같습니다.

  1. 사용자가 존재합니까?
  2. 사용자가 존재하는 경우 사용자의 /home 디렉토리를 백업하고 사용자 이름을 삭제한 후 /root/DeletedUsers에 넣습니다.
  3. /root/DeletedUsers 디렉터리가 없으면 새로 만듭니다.
  4. 이 사용자에 대한 방화벽 규칙이 있는 경우 해당 규칙의 결과와 어떤 노드에 대한 결과를 이메일로 보내주십시오.
  5. 사용자가 sudoers에 존재하는 경우 삭제하지 말고 주석 처리하세요.

이것이 내가 지금까지 가지고 있는 것입니다. RHN Satellite에서 실행하기 전에 작동하는지 확인하고 싶습니다. 권장 사항을 변경한 후. 이것이 지금 나타나는 새로운 오류입니다.

[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

답변1

이를 사용하여 getent사용자가 존재하는지 확인하는 것이 좋습니다. 이 스크립트가 도움이 될 것입니다.

##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

스크립트를 호출한 ./deal ray[4]다음 다른 사용자를 위해 실행해야 하는 경우 를 사용하여 호출할 수 있습니다 ./deal ray[6]. 아직 내 시스템에서 스크립트를 테스트하지는 않았지만 나중에 다른 사용자를 제거해야 하는 경우에 도움이 될 것입니다. 스크립트를 수정할 필요는 없지만 사용자 이름을 매개변수로 사용하여 호출하면 됩니다.

편집하다

derobert의 제안에 따라 -p플래그를 사용하면 디렉토리 테스트를 생략할 수 있습니다.

답변2

실제로 고유한 경우 Ray[46]스크립트의 거의 모든 테스트가 중복됩니다.

printf %s\\n 123 456 | sed '/2/s///'

#OUTPUT#
13
456

위의 코드는 입력에서 /addressed/string 을 포함하는 행을 검색하고 2, 발견되면 주소 지정된 문자열을 제외한 모든 항목을 포함하도록 해당 행을 변경합니다. 아래 삭제하시면 됩니다오직주소 지정 라인:

printf %s\\n 123 456 | sed '/2/d'

#OUTPUT#
456

그러면 필요가 grep없습니다 sed. 실제로 그보다 grep더 빠르다 .sedgrep 그리고 [test]그 출력그 다음에Invoke sed, sed문제가 있는 문자열과 관련된 모든 파일의 삭제가 완료되었을 수 있습니다.

grep그리고 다시 말하지만, 어떤 이유로 든 정말로 이 작업을 수행하고 싶다면 sed다음이 더 중요할 것입니다.

remove=string ; for f in $(grep -l "$remove" $file_list) ; do 
    printf %s "$(sed "/$remove/s///" "$f")" >"$f" ; done

또는 GNU를 사용하십시오 sed:

sed -i "/$remove/s///" $(grep -l "$remove" $file_list)

위에서 언급했듯이 mkdir -p대상 디렉터리는 필요한 경우에만 생성되므로 이것으로 충분합니다.

mkdir -p /root/DeletedUsers ; mv /home/$string "$_"

모든 로그를 가져와서 어떤 일이 발생한 머신에서만 수행된 작업을 정확하게 확인할 수도 있습니다.

#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'

위의 내용은 대상 사용자에게 $HOME사용자 이름의 이름을 딴 in이 있다고 가정합니다. /home가정이 맞다면 대상 사용자의 사용자 이름이 등록된 모든 컴퓨터에서만 작업을 수행합니다.

grep같은 작업을 수행할 필요가 없으면 tee생략할 수도 있습니다 . sed줄을 다음과 같이 변경 하십시오 .

for f in $file_list ; do 
    sed -ni "/$remove/{h;s///};p;\$!b;x;/$remove/s|.*|$f|w /dev/stderr" "$f"
done

이렇게 하면 string 을 포함하는 sed's각 새 줄로 예약된 공간을 덮어씁니다 . 스캔을 마치고 마지막 줄에 도달하면 예약된 공간으로 전환하고 참조가 있으면 파일 이름을 씁니다.sed"$remove"sed's$removestderr

위에서 작성한 것과 같은 스크립트를 자신의 컴퓨터에서 실행하고 모든 대상에 연결하면 각 대상에서 자신의 컴퓨터로 연결을 ssh열 필요가 없습니다. 이미 연결되어 있기 때문입니다. ssh마지막 항목 |pipe과 그 이후의 모든 항목을 삭제하고 다음을 수행할 수 있습니다.

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

관련 정보