我需要创建一个 Bash 脚本来删除用户。
我们使用 RHEL 版本 4、5 和 6。
假设用户名是 Ray4 和 Ray6,脚本名称是 deal。
该脚本的具体任务是:
- 用户是否存在?
- 如果用户存在,备份该用户的/home目录,删除用户名并放置在/root/DeletedUsers中
- 如果 /root/DeletedUsers 目录不存在,请创建它。
- 如果该用户存在任何防火墙规则,请通过电子邮件将这些规则的结果以及在哪些节点上的结果发送给我。
- 如果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
比 更快sed
,但在调用所需的时间grep
和 [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
$remove
stderr
如果你从你自己的机器上运行一个像我上面写的那样的脚本,并且你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