删除账户脚本

本文详细介绍了如何编写一个bash脚本来安全删除Linux系统中的本地用户账户,包括获取账户名、确认删除、终止进程、查找并处理用户文件,以及最终删除账户的步骤。脚本具有交互性,确保用户在每个关键步骤都能确认操作,增加了账户管理的安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

管理本地用户账户绝不仅仅是添加、修改和删除,还需考虑安全问题、保留工作的需求,以及精确删除账户。

一、基本功能拆解

  • 删除本地账户属于更复杂的账户管理任务,至少需要 4 个步骤
  1. 获取正确的待删除用户账户名
  2. 杀死”系统中正在运行的属于该账户的进程
  3. 确认系统中属于该账户的所有文件
  4. 删除该用户账户

1.1 获取正确的账户名

可以使用 read 命令获取账户名称。

  • read 命令中加入-t 选项,在超时退出之前给用户 60 秒的时间回答问题:
echo "Please enter the username of the user " 
echo -e "account you wish to delete from system: \c" 
read -t 60 answer
  • 最好再给脚本用户 3 次机会来回答问题:
while [ -z "$answer" ]; do
    echo "Please enter the username of the user "
    echo -e "account you wish to delete from system: \c"
    read -t 60 answer

    # 记录当前不作答次数。
    ask_count=$((ask_count + 1))

    case $ask_count in
    2)
        echo
        echo "Please answer the question."
        echo
        ;;
    3)
        echo
        echo "One last try...please answer the question."
        echo
        ;;
    4)
        echo
        echo "Since you refuse to answer the question..."
        echo "exiting program."
        echo
        #
        exit
        ;;
    esac
done

1.2 通过函数获取正确的账户名

我们可以将上面这段代码加入对脚本用户的提问,并放到一个函数以便在脚本中重复使用

  • 创建函数
#!/bin/bash
get_answer() {
    while [ -z "$answer" ]; do
        echo "Please enter the username of the user "
        echo -e "account you wish to delete from system: \c"

        ask_count=$((ask_count + 1))
        case $ask_count in
        2)
            echo
            echo "Please answer the question."
            echo
            ;;
        3)
            echo
            echo "One last try...please answer the question."
            echo
            ;;
        4)
            echo
            echo "Since you refuse to answer the question..."
            echo "exiting program."
            echo
            #
            exit
            ;;
        esac

        echo
        
		# line1 和 line2 用于询问不同的问题。
        if [ -n "$line2" ]; then
            echo $line1
            echo -e $line2" \c"
        else
            echo -e $line1" \c"
        fi

        # 超时 60 s。
        read -t 60 answer
    done
    
    # 清除变量。
    unset line1
    unset line2
}

  • 调用函数
line1="Please enter the username of the user " 
line2="account you wish to delete from system:" 
get_answer 
user_account=$answer

1.3 核实输入的账户名

  • 考虑到可能存在输入错误,应该核实一下输入的用户账户名。这很容易,因为处理提问的代码是现成的:
line1="Is $user_account the user account " 
line2="you wish to delete from the system? [y/n]" 
get_answer
  • 如果用户回答了“yes”,那么我们就得到了确认,脚本也能够继续执行。

  • 脚本要在不同的位置多次处理脚本用户的“yes/no”回答,因此有必要创建一个函数来处理这个任务:

process_answer() {
    # cut命令截取字符串(只保留第一个字符)。
    answer=$(echo $answer | cut -c1)
    #
    case $answer in
    y | Y) ;;

    *)
        echo
        echo $exit_line1
        echo $exit_line2
        echo
        exit
        ;;
    esac
    #
    unset exit_line1
    unset exit_line2
    #
}
  • 现在调用函数就可以处理脚本用户的回答了:
exit_line1="Because the account, $user_account, is not " 
exit_line2="the one you wish to delete, we are leaving the script..." 
process_answer

1.4 确认账户是否存在

  • 安全起见,最好将完整的账户记录显示给脚本用户,再次核实这就是要删除的账户
# grep 的-w 选项会精确匹配特定的用户账户。
user_account_record=$(cat /etc/passwd | grep -w $user_account)
  • 如果在 /etc/passwd 中没找到指定账户,则 $? 变量会被设置为 1:
if [ $? -eq 1 ]; then
    echo
    echo "Account, $user_account, not found. "
    echo "Leaving the script..."
    echo
    exit
fi
  • 就算找到了记录,仍然需要向脚本用户核实这是不是正确的账户
echo "I found this record:"
echo $user_account_record
echo
#
line1="Is this the correct User Account? [y/n]"
get_answer
#
exit_line1="Because the account, $user_account, is not"
exit_line2="the one you wish to delete, we are leaving the script..."
process_answer

1.5 删除账户进程

  • 脚本可以使用 ps 命令和 -u 选项来找出属于该账户的所有运行中的进程。记得将命令输出重定向到 /dev/null,这样脚本用户在屏幕上就看不到任何显示信息了:
ps -u $user_account >/dev/null
  • 如果 ps 命令的退出状态码返回 1,那么表明系统中没有属于该用户账户的进程在运行。如果退出状态码返回 0,则表明存在相关进程
case $? in
1) # No processes running for this User Account
    #
    echo "There are no processes for this account currently running."
    echo
    ;;
0) # Processes running for this User Account.
    # Ask Script User if wants us to kill the processes.
    #
    echo "$user_account has the following process(es) running:"
    ps -u $user_account
    #
    line1="Would you like me to kill the process(es)? [y/n]"
    get_answer
    #
    ;;
esac
  • 存在相关进程时,脚本需要询问脚本用户是否要“杀死”这些进程
answer=$(echo $answer | cut -c1)
#
case $answer in
y | Y) # If user answers "yes",
    # kill User Account processes.
    [...]
    ;;
*) # If user answers anything but "yes", do not kill.
    echo
    echo "Will not kill the process(es)"
    echo
    #
    ;;
esac
  • 需要以下命令完成“杀死”该用户账户的进程操作:
# 1.收集当前处于运行状态且属于该用户账户的进程的 PID。
command_1="ps -u $user_account --no-heading"

# 2.提取 PID。
gawk '{print $1}'

# 3.xargs 可以使用从标准输入 STDIN 获取的命令参数并执行指定的命令。它非常适合放在管道的末尾处。
# 实际上,xarg 命令负责“杀死”PID 所对应的进程。
# xargs(-d)指定换行为分隔符,通过完整路径的命令(sudo)和(kill)“杀死”进程。
command_3="xargs -d \\n /usr/bin/sudo /bin/kill -9"
  • 整个命令管道如下所示:
$command_1 | gawk '{print $1}' | $command_3
  • 下面是“杀死”用户账户所有运行进程的完整 case 语句:
# 如果回答yes。
case $answer in
y | Y)
    echo
    echo "Killing off process(es)... "

    # 1.收集当前处于运行状态且属于该用户账户的进程的 PID。
    command_1="ps -u $user_account --no-heading"

    # 2.xargs 命令会将 gawk 命令生成的 PID 列作为输入,创建并执行 kill 命令,“杀死”该用户所有的运行进程。
    command_3="xargs -d \\n /usr/bin/sudo /bin/kill -9"

    # 3.收集并提取当前账户进程的PID,执行“杀死”进程操作。
    $command_1 | gawk '{print $1}' | $command_3

    echo
    echo "Process(es) killed."
    ;;
*)
    echo
    echo "Will not kill process(es)."
    ;;
esac

1.6 查找账户文件

如果待删除账户的 UID 是 1003,而你没有删除或修改文件的所属关系,那么下一个 UID 为 1003 的账户将拥有这些文件。这种情况必然是一种安全隐患

  • find 命令会使用 -user 查找整个文件系统,准确找出属于 user_account 的所有文件:
find / -user $user_account > $report_file

1.7 删除账户

删除系统中的用户账户时一定要小心谨慎。因此,不妨再询问一遍,脚本用户是否真的想删除该账户。

  • 再次询问是否删除
line1="Remove $user_account's account from system? [y/n]" 
get_answer 
# 
exit_line1="Since you do not wish to remove the user account," 
exit_line2="$user_account at this time, exiting the script..." 
process_answer
  • 最后,就是脚本的主要任务了:从系统中真正地删除指定用户账户。
userdel $user_account

二、完整的脚本内容

Delete_User.sh 与脚本用户之间具有很强的交互性。因此,有一点很重要,即在该脚本的执行过程中,要备注大量的文字信息以让脚本用户了解正在发生的事情

  • 下面是完整的 Delete_User.sh 脚本:
#!/bin/bash
####################  定义询问用户的函数  ####################
function get_answer {

    # 变量初始化。
    unset answer
    ask_count=0

    # 没有答案时继续询问。
    while [ -z "$answer" ]; do

        # 记录当前不作答次数。
        ask_count=$((ask_count + 1))

        # 根据次数给出相应提示。
        case $ask_count in
        2)
            echo
            echo "Please answer the question."
            echo
            ;;
        3)
            echo
            echo "One last try...please answer the question."
            echo
            ;;
        4)
            echo
            echo "Since you refuse to answer the question..."
            echo "exiting program."
            echo
            # 超过三次则退出。
            exit
            ;;
        esac
        #
        # 打印询问内容。
        if [ -n "$line2" ]; then
            echo $line1
            echo -e $line2" \c"
        else
            echo -e $line1" \c"
        fi
        #
        # 设置 60 s 超时作答。
        read -t 60 answer
    done

    # 重置变量。
    unset line1
    unset line2
    #
}

####################  定义用户确认函数  ####################
function process_answer {
    # 截取字符串。(只保留第一个字符。)
    answer=$(echo $answer | cut -c1)

    case $answer in
    y | Y)
        # 如果回答的是“yes”。则什么也不做。
        ;;
    *)
        # 如果回答不是“yes”,则退出脚本。
        echo
        echo $exit_line1
        echo $exit_line2
        echo
        exit
        ;;
    esac

    # 重置变量。
    unset exit_line1
    unset exit_line2
    #
}

####################  具体的执行逻辑:  ####################
#
####################  【第一步】:获取并确认待删除的用户账户名  ####################
echo "Step #1 - Determine User Account name to Delete "
echo
line1="Please enter the username of the user "
line2="account you wish to delete from system:"
get_answer
user_account=$answer
#
# 询问是否为希望移除的用户账户。
line1="Is $user_account the user account "
line2="you wish to delete from the system? [y/n]"
get_answer
#
# 调用确认函数。(如果用户的回答不是“yes”,则退出脚本。)
exit_line1="Because the account, $user_account, is not "
exit_line1="the one you wish to delete, we are leaving the script..."
process_answer
#
# 检查是否确实是系统上的一个账户。
user_account_record=$(cat /etc/passwd | grep -w $user_account)
# 如果没有找到帐号,退出脚本。
if [ $? -eq 1 ]; then
    echo
    echo "Account, $user_account, not found. "
    echo "Leaving the script..."
    echo
    exit
fi
#
echo
echo "I found this record:"
echo $user_account_record
echo
#
line1="Is this the correct User Account? [y/n]"
get_answer
#
# 再次确认用户回答,如果不是“yes”,则退出脚本。
exit_line1="Because the account, $user_account, is not "
exit_line2="the one you wish to delete, we are leaving the script..."
process_answer
#

####################  【第二步】:查找并“杀死”该用户账户的所有进程  ####################
echo
echo "Step #2 - Find process on system belonging to user account"
echo
# 列出正在运行的用户进程。
ps -u $user_account >/dev/null
case $? in
1)
    # 退出状态码是1,表示此用户帐户没有正在运行的进程。
    echo "There are no processes for this account 
currently running."
    echo
    ;;
0)
    # 退出状态码是0,表示该用户帐户正在运行的进程。
    # 询问脚本用户是否希望“杀死”进程。
    echo "$user_account has the following process(es) running:"
    ps -u $user_account
    #
    line1="Would you like me to kill the process(es)? [y/n]"
    get_answer
    # 截取用户回答。
    answer=$(echo $answer | cut -c1)
    case $answer in
    y | Y)
        # 如果回答“yes”,则准备“杀死”进程。
        echo
        echo "Killing off process(es)..."

        # 列出用户正在运行的进程。
        command_1="ps -u $user_account --no-heading"

        # “杀死”进程的命令。
        command_3="xargs -d \\n /usr/bin/sudo /bin/kill -9"
        #
        # 收集并提取当前账户进程的PID,执行“杀死”进程操作。
        $command_1 | gawk '{print $1}' | $command_3
        #
        echo
        echo "Process(es) killed."
        ;;
    *)
        # 没有回答“yes”,则不“杀死”进程。
        echo
        echo "Will not kill process(es)."
        ;;
    esac
    ;;
esac
#

####################  【第三步】:创建该用户账户所拥有的全部文件的报告  ####################
echo
echo "Step #3 - Find files on system belonging to user account"
echo
echo "Creating a report of all files owned by $user_account."
echo
echo "It is recommended that you backup/archive these files,"
echo "and then do one of two things:"
echo " 1) Delete the files"
echo " 2) Change the files' ownership to a current user account."
echo
echo "Please wait. This may take a while..."
# 日期及文件信息。
report_date=$(date +%y%m%d)
report_file="$user_account"_Files_"$report_date".rpt
# 查找整个文件系统,准确找出属于该用户的所有文件。
find / -user $user_account >$report_file 2>/dev/null
#
echo
echo "Report is complete."
echo "Name of report: $report_file"
echo -n "Location of report: "
pwd
echo
#

####################  【第四步】:删除该用户账户  ####################
echo
echo "Step #4 - Remove user account"
echo
#
line1="Do you wish to remove $user_account's account from system? [y/n]"
get_answer
#
exit_line1="Since you do not wish to remove the user account,"
exit_line2="$user_account at this time, exiting the script..."
process_answer
# 删除用户账户。
userdel $user_account
echo
echo "User account, $user_account, has been removed"
echo
# 退出。
exit
#

三、运行脚本

必须以 root 用户身份登录,或者使用 sudo 命令运行这种脚本。

  • 运行脚本
# 1.赋予执行权限。
[root@VM-8-11-centos script]# chmod u+x Delete_User.sh 
[root@VM-8-11-centos script]# 
[root@VM-8-11-centos script]# ls -og Delete_User.sh 
-rwxr--r-- 1 5988 Jul 15 07:24 Delete_User.sh
[root@VM-8-11-centos script]# 

# 2.运行脚本。
[root@VM-8-11-centos script]# sudo ./Delete_User.sh 
Step #1 - Determine User Account name to Delete 

Please enter the username of the user
account you wish to delete from system: jan2   
Is jan2 the user account
you wish to delete from the system? [y/n] yes

I found this record:
jan2:x:1009:1009::/home/tmp/:/bin/bash

Is this the correct User Account? [y/n] y

Step #2 - Find process on system belonging to user account

There are no processes for this account 
currently running.


Step #3 - Find files on system belonging to user account

Creating a report of all files owned by jan2.

It is recommended that you backup/archive these files,
and then do one of two things:
 1) Delete the files
 2) Change the files' ownership to a current user account.

Please wait. This may take a while...

Report is complete.
Name of report: jan2_Files_230715.rpt
Location of report: /home/script


Step #4 - Remove user account

Do you wish to remove jan2's account from system? [y/n] yes   

User account, jan2, has been removed

[root@VM-8-11-centos script]# 

# 3.查看该用户账户所拥有的全部文件的报告。
[root@VM-8-11-centos script]# cat jan2_Files_230715.rpt 
/var/spool/mail/jan2
[root@VM-8-11-centos script]# 

# 4.查看该账户是否还存在。
[root@VM-8-11-centos script]# grep ^jan2 /etc/passwd
[root@VM-8-11-centos script]# 

四、结束语


“-------怕什么真理无穷,进一寸有一寸的欢喜。”

微信公众号搜索:饺子泡牛奶

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值