Files
linux-bash/user-manager/user-manager.sh
2026-02-17 17:28:37 +08:00

1220 lines
33 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# ============================================================================
# Linux 用户和组管理脚本 (增强版)
# 适用于: Debian/Ubuntu (amd64/arm64)
# 用法: curl -fsSL "https://pan.shumengya.top/d/scripts/user_manager.sh" | bash
# 或者: sudo bash user_manager.sh
# ============================================================================
set -euo pipefail
# ============================================================================
# 颜色定义
# ============================================================================
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[0;33m'
readonly BLUE='\033[0;34m'
readonly CYAN='\033[0;36m'
readonly MAGENTA='\033[0;35m'
readonly BOLD='\033[1m'
readonly NC='\033[0m' # 无颜色
# ============================================================================
# 日志函数
# ============================================================================
log_info() {
echo -e "${GREEN}[信息]${NC} $*"
}
log_warn() {
echo -e "${YELLOW}[警告]${NC} $*"
}
log_error() {
echo -e "${RED}[错误]${NC} $*" >&2
}
log_success() {
echo -e "${GREEN}[成功]${NC} $*"
}
log_title() {
echo -e "\n${CYAN}${BOLD}=== $* ===${NC}\n"
}
# ============================================================================
# 系统检测和初始化
# ============================================================================
init_system() {
# 检查root权限
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
log_error "需要root权限运行此脚本"
log_info "请使用: sudo bash $0"
exit 1
fi
# 检测操作系统
if [ ! -f /etc/os-release ]; then
log_error "无法检测操作系统版本"
exit 1
fi
. /etc/os-release
OS_NAME="$NAME"
OS_VERSION="${VERSION_ID:-未知}"
# 检测架构
ARCH=$(uname -m)
case "$ARCH" in
x86_64|amd64)
ARCH_NAME="amd64"
;;
aarch64|arm64)
ARCH_NAME="arm64"
;;
*)
log_warn "未知架构: $ARCH"
ARCH_NAME="$ARCH"
;;
esac
# 检查是否为Debian/Ubuntu系统
if [[ ! "$OS_NAME" =~ (Debian|Ubuntu) ]]; then
log_warn "此脚本主要为Debian/Ubuntu设计当前系统: $OS_NAME"
read -p "是否继续? (y/n): " -n 1 -r < /dev/tty
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 0
fi
fi
log_info "系统: $OS_NAME $OS_VERSION"
log_info "架构: $ARCH_NAME ($ARCH)"
# 设置sudo组名
SUDO_GROUP="sudo"
}
# ============================================================================
# 工具函数
# ============================================================================
# 检查用户是否存在
user_exists() {
id "$1" &>/dev/null
}
# 检查组是否存在
group_exists() {
getent group "$1" &>/dev/null
}
# 获取用户的UID
get_user_uid() {
id -u "$1" 2>/dev/null
}
# 获取用户的主组
get_user_primary_group() {
id -gn "$1" 2>/dev/null
}
# 获取用户的所有附加组
get_user_groups() {
id -Gn "$1" 2>/dev/null | tr ' ' ','
}
# 检查用户是否在某个组中
user_in_group() {
local username="$1"
local groupname="$2"
id -nG "$username" 2>/dev/null | grep -qw "$groupname"
}
# 验证用户名格式
validate_username() {
local username="$1"
if [[ ! "$username" =~ ^[a-z_][a-z0-9_-]*[$]?$ ]]; then
log_error "用户名格式无效: $username"
log_info "用户名必须以小写字母或下划线开头,只能包含小写字母、数字、下划线和连字符"
return 1
fi
if [ ${#username} -gt 32 ]; then
log_error "用户名过长 (最大32字符): $username"
return 1
fi
return 0
}
# 验证组名格式
validate_groupname() {
local groupname="$1"
if [[ ! "$groupname" =~ ^[a-z_][a-z0-9_-]*[$]?$ ]]; then
log_error "组名格式无效: $groupname"
log_info "组名必须以小写字母或下划线开头,只能包含小写字母、数字、下划线和连字符"
return 1
fi
if [ ${#groupname} -gt 32 ]; then
log_error "组名过长 (最大32字符): $groupname"
return 1
fi
return 0
}
# 安全读取密码
read_password() {
local password
local password_confirm
while true; do
read -s -p "请输入密码: " password < /dev/tty
echo >&2
if [ ${#password} -lt 6 ]; then
log_error "密码长度至少6个字符"
continue
fi
read -s -p "请再次输入密码: " password_confirm < /dev/tty
echo >&2
if [ "$password" != "$password_confirm" ]; then
log_error "两次输入的密码不一致"
continue
fi
echo "$password"
return 0
done
}
# 确认操作
confirm_action() {
local prompt="$1"
local response
read -p "${prompt} (y/n): " -n 1 -r response < /dev/tty
echo
[[ $response =~ ^[Yy]$ ]]
}
# 短暂延迟以便用户查看结果(用于添加、删除、修改等操作)
show_result() {
sleep 1.5
}
# 等待用户按回车继续(用于查看、列出等操作)
pause_for_view() {
echo
read -p "按回车键返回菜单..." -r < /dev/tty
}
# ============================================================================
# 用户管理功能
# ============================================================================
# 添加用户
add_user() {
log_title "添加新用户"
# 输入用户名
local username
while true; do
read -p "请输入用户名: " username < /dev/tty
username=$(echo "$username" | xargs) # 去除首尾空格
if [ -z "$username" ]; then
log_error "用户名不能为空"
continue
fi
if ! validate_username "$username"; then
continue
fi
if user_exists "$username"; then
log_error "用户 '$username' 已存在"
continue
fi
break
done
# 输入主目录
local homedir
read -p "主目录 (默认: /home/$username): " homedir < /dev/tty
homedir=${homedir:-/home/$username}
# 输入Shell
local usershell
echo "可用的Shell:"
cat /etc/shells | grep -v "^#" | nl
read -p "Shell (默认: /bin/bash): " usershell < /dev/tty
usershell=${usershell:-/bin/bash}
# 验证Shell是否存在
if [ ! -f "$usershell" ]; then
log_warn "Shell '$usershell' 不存在,使用默认 /bin/bash"
usershell="/bin/bash"
fi
# 输入密码
log_info "设置用户密码 (最少6个字符)"
local password
password=$(read_password)
# 创建用户
log_info "正在创建用户 '$username'..."
if useradd -m -d "$homedir" -s "$usershell" "$username" 2>/dev/null; then
# 设置密码
echo "$username:$password" | chpasswd
log_success "用户 '$username' 创建成功"
log_info "UID: $(get_user_uid "$username")"
log_info "主目录: $homedir"
log_info "Shell: $usershell"
# 询问是否添加sudo权限
if confirm_action "是否授予sudo权限?"; then
add_user_to_sudo "$username"
fi
# 询问是否添加到其他组
if confirm_action "是否添加到其他组?"; then
add_user_to_groups_interactive "$username"
fi
else
log_error "创建用户失败"
return 1
fi
show_result
}
# 删除用户
delete_user() {
log_title "删除用户"
# 列出普通用户
list_normal_users_simple
local username
read -p "请输入要删除的用户名: " username < /dev/tty
username=$(echo "$username" | xargs)
if [ -z "$username" ]; then
log_error "用户名不能为空"
return 1
fi
if ! user_exists "$username"; then
log_error "用户 '$username' 不存在"
return 1
fi
# 获取用户信息
local uid=$(get_user_uid "$username")
local homedir=$(getent passwd "$username" | cut -d: -f6)
log_warn "即将删除用户: $username (UID: $uid)"
log_warn "主目录: $homedir"
if ! confirm_action "确认删除此用户?"; then
log_info "已取消删除操作"
return 0
fi
# 询问是否删除主目录
local delete_home=""
if confirm_action "是否同时删除主目录和邮件?"; then
delete_home="-r"
fi
# 执行删除
if userdel $delete_home "$username" 2>/dev/null; then
log_success "用户 '$username' 已删除"
else
log_error "删除用户失败"
fi
show_result
}
# 修改用户信息
modify_user() {
log_title "修改用户信息"
# 列出普通用户
list_normal_users_simple
local username
read -p "请输入要修改的用户名: " username < /dev/tty
username=$(echo "$username" | xargs)
if [ -z "$username" ]; then
log_error "用户名不能为空"
return 1
fi
if ! user_exists "$username"; then
log_error "用户 '$username' 不存在"
return 1
fi
# 显示修改菜单
while true; do
echo
log_info "当前用户: $username"
log_info "UID: $(get_user_uid "$username")"
log_info "主组: $(get_user_primary_group "$username")"
log_info "所有组: $(get_user_groups "$username")"
log_info "主目录: $(getent passwd "$username" | cut -d: -f6)"
log_info "Shell: $(getent passwd "$username" | cut -d: -f7)"
echo
echo "请选择要修改的项目:"
echo " 1) 修改主目录"
echo " 2) 修改Shell"
echo " 3) 修改主组"
echo " 4) 修改用户名"
echo " 5) 锁定/解锁用户"
echo " 0) 返回上级菜单"
echo
local choice
read -p "请选择 [0-5]: " choice < /dev/tty
case $choice in
1)
modify_user_home "$username"
;;
2)
modify_user_shell "$username"
;;
3)
modify_user_primary_group "$username"
;;
4)
modify_username "$username"
return 0
;;
5)
toggle_user_lock "$username"
;;
0)
return 0
;;
*)
log_error "无效的选择"
;;
esac
done
}
# 修改用户主目录
modify_user_home() {
local username="$1"
local current_home=$(getent passwd "$username" | cut -d: -f6)
log_info "当前主目录: $current_home"
local new_home
read -p "新主目录: " new_home < /dev/tty
if [ -z "$new_home" ]; then
log_error "主目录不能为空"
return 1
fi
if usermod -d "$new_home" "$username" 2>/dev/null; then
log_success "主目录已修改为: $new_home"
if confirm_action "是否移动现有文件到新目录?"; then
if [ -d "$current_home" ]; then
usermod -m -d "$new_home" "$username" 2>/dev/null
log_success "文件已移动"
fi
fi
else
log_error "修改主目录失败"
fi
}
# 修改用户Shell
modify_user_shell() {
local username="$1"
local current_shell=$(getent passwd "$username" | cut -d: -f7)
log_info "当前Shell: $current_shell"
echo "可用的Shell:"
cat /etc/shells | grep -v "^#" | nl
local new_shell
read -p "新Shell: " new_shell < /dev/tty
if [ -z "$new_shell" ]; then
log_error "Shell不能为空"
return 1
fi
if [ ! -f "$new_shell" ]; then
log_error "Shell '$new_shell' 不存在"
return 1
fi
if usermod -s "$new_shell" "$username" 2>/dev/null; then
log_success "Shell已修改为: $new_shell"
else
log_error "修改Shell失败"
fi
}
# 修改用户主组
modify_user_primary_group() {
local username="$1"
local current_group=$(get_user_primary_group "$username")
log_info "当前主组: $current_group"
# 列出所有组
echo "系统中的组:"
getent group | cut -d: -f1 | column
local new_group
read -p "新主组: " new_group < /dev/tty
if [ -z "$new_group" ]; then
log_error "组名不能为空"
return 1
fi
if ! group_exists "$new_group"; then
log_error "组 '$new_group' 不存在"
if confirm_action "是否创建此组?"; then
if groupadd "$new_group" 2>/dev/null; then
log_success "组 '$new_group' 已创建"
else
log_error "创建组失败"
return 1
fi
else
return 1
fi
fi
if usermod -g "$new_group" "$username" 2>/dev/null; then
log_success "主组已修改为: $new_group"
else
log_error "修改主组失败"
fi
}
# 修改用户名
modify_username() {
local old_username="$1"
log_warn "修改用户名是一个敏感操作"
local new_username
read -p "新用户名: " new_username < /dev/tty
new_username=$(echo "$new_username" | xargs)
if [ -z "$new_username" ]; then
log_error "用户名不能为空"
return 1
fi
if ! validate_username "$new_username"; then
return 1
fi
if user_exists "$new_username"; then
log_error "用户 '$new_username' 已存在"
return 1
fi
if ! confirm_action "确认将 '$old_username' 改名为 '$new_username'?"; then
return 0
fi
if usermod -l "$new_username" "$old_username" 2>/dev/null; then
log_success "用户名已修改为: $new_username"
# 询问是否同时修改主目录名
if confirm_action "是否同时修改主目录名?"; then
local old_home=$(getent passwd "$new_username" | cut -d: -f6)
local new_home=$(dirname "$old_home")/"$new_username"
if usermod -d "$new_home" -m "$new_username" 2>/dev/null; then
log_success "主目录已修改为: $new_home"
fi
fi
else
log_error "修改用户名失败"
fi
}
# 锁定/解锁用户
toggle_user_lock() {
local username="$1"
# 检查用户是否被锁定
if passwd -S "$username" 2>/dev/null | grep -q " L "; then
log_info "用户 '$username' 当前状态: 已锁定"
if confirm_action "是否解锁此用户?"; then
if passwd -u "$username" 2>/dev/null; then
log_success "用户已解锁"
else
log_error "解锁失败"
fi
fi
else
log_info "用户 '$username' 当前状态: 未锁定"
if confirm_action "是否锁定此用户?"; then
if passwd -l "$username" 2>/dev/null; then
log_success "用户已锁定"
else
log_error "锁定失败"
fi
fi
fi
}
# 修改用户密码
change_user_password() {
log_title "修改用户密码"
list_normal_users_simple
local username
read -p "请输入用户名: " username < /dev/tty
username=$(echo "$username" | xargs)
if [ -z "$username" ]; then
log_error "用户名不能为空"
return 1
fi
if ! user_exists "$username"; then
log_error "用户 '$username' 不存在"
return 1
fi
log_info "为用户 '$username' 设置新密码"
local password
password=$(read_password)
if echo "$username:$password" | chpasswd 2>/dev/null; then
log_success "密码修改成功"
else
log_error "密码修改失败"
fi
show_result
}
# 添加用户到sudo组
add_user_to_sudo() {
local username="$1"
if ! group_exists "$SUDO_GROUP"; then
log_warn "sudo组 ($SUDO_GROUP) 不存在,正在创建..."
if groupadd "$SUDO_GROUP" 2>/dev/null; then
log_success "sudo组已创建"
else
log_error "创建sudo组失败"
return 1
fi
fi
if user_in_group "$username" "$SUDO_GROUP"; then
log_info "用户 '$username' 已经拥有sudo权限"
return 0
fi
if usermod -aG "$SUDO_GROUP" "$username" 2>/dev/null; then
log_success "已授予用户 '$username' sudo权限"
else
log_error "授予sudo权限失败"
return 1
fi
}
# 交互式添加用户到多个组
add_user_to_groups_interactive() {
local username="$1"
echo "系统中的组:"
getent group | cut -d: -f1 | column
local groups
read -p "请输入要添加的组 (用逗号或空格分隔): " groups < /dev/tty
if [ -z "$groups" ]; then
return 0
fi
# 将逗号替换为空格
groups=$(echo "$groups" | tr ',' ' ')
for group in $groups; do
group=$(echo "$group" | xargs)
if [ -z "$group" ]; then
continue
fi
if ! group_exists "$group"; then
log_warn "组 '$group' 不存在"
if confirm_action "是否创建组 '$group'?"; then
if groupadd "$group" 2>/dev/null; then
log_success "组 '$group' 已创建"
else
log_error "创建组 '$group' 失败"
continue
fi
else
continue
fi
fi
if user_in_group "$username" "$group"; then
log_info "用户已在组 '$group' 中"
else
if usermod -aG "$group" "$username" 2>/dev/null; then
log_success "已将用户添加到组 '$group'"
else
log_error "添加到组 '$group' 失败"
fi
fi
done
}
# ============================================================================
# 组管理功能
# ============================================================================
# 管理用户组成员
manage_user_groups() {
log_title "管理用户组成员"
list_normal_users_simple
local username
read -p "请输入用户名: " username < /dev/tty
username=$(echo "$username" | xargs)
if [ -z "$username" ]; then
log_error "用户名不能为空"
return 1
fi
if ! user_exists "$username"; then
log_error "用户 '$username' 不存在"
return 1
fi
while true; do
echo
log_info "用户: $username"
log_info "主组: $(get_user_primary_group "$username")"
log_info "所有组: $(get_user_groups "$username")"
echo
echo "请选择操作:"
echo " 1) 添加到组"
echo " 2) 从组中移除"
echo " 3) 添加/移除sudo权限"
echo " 0) 返回上级菜单"
echo
local choice
read -p "请选择 [0-3]: " choice < /dev/tty
case $choice in
1)
add_user_to_groups_interactive "$username"
;;
2)
remove_user_from_group "$username"
;;
3)
toggle_sudo_permission "$username"
;;
0)
return 0
;;
*)
log_error "无效的选择"
;;
esac
done
}
# 从组中移除用户
remove_user_from_group() {
local username="$1"
local current_groups=$(id -Gn "$username" | tr ' ' '\n' | grep -v "^$(get_user_primary_group "$username")$")
if [ -z "$current_groups" ]; then
log_info "用户没有附加组"
return 0
fi
echo "用户 '$username' 的附加组:"
echo "$current_groups" | nl
local groupname
read -p "请输入要移除的组名: " groupname < /dev/tty
groupname=$(echo "$groupname" | xargs)
if [ -z "$groupname" ]; then
return 0
fi
if ! user_in_group "$username" "$groupname"; then
log_error "用户不在组 '$groupname' 中"
return 1
fi
if [ "$groupname" = "$(get_user_primary_group "$username")" ]; then
log_error "不能移除主组"
return 1
fi
if gpasswd -d "$username" "$groupname" 2>/dev/null; then
log_success "已将用户从组 '$groupname' 中移除"
else
log_error "移除失败"
fi
}
# 切换sudo权限
toggle_sudo_permission() {
local username="$1"
if user_in_group "$username" "$SUDO_GROUP"; then
log_info "用户当前拥有sudo权限"
if confirm_action "是否移除sudo权限?"; then
if gpasswd -d "$username" "$SUDO_GROUP" 2>/dev/null; then
log_success "sudo权限已移除"
else
log_error "移除sudo权限失败"
fi
fi
else
log_info "用户当前没有sudo权限"
if confirm_action "是否授予sudo权限?"; then
add_user_to_sudo "$username"
fi
fi
}
# 添加组
add_group() {
log_title "添加新组"
local groupname
while true; do
read -p "请输入组名: " groupname < /dev/tty
groupname=$(echo "$groupname" | xargs)
if [ -z "$groupname" ]; then
log_error "组名不能为空"
continue
fi
if ! validate_groupname "$groupname"; then
continue
fi
if group_exists "$groupname"; then
log_error "组 '$groupname' 已存在"
continue
fi
break
done
# 询问是否指定GID
local gid_option=""
if confirm_action "是否指定GID?"; then
local gid
read -p "请输入GID: " gid < /dev/tty
if [[ "$gid" =~ ^[0-9]+$ ]]; then
gid_option="-g $gid"
else
log_warn "GID无效将自动分配"
fi
fi
if groupadd $gid_option "$groupname" 2>/dev/null; then
local new_gid=$(getent group "$groupname" | cut -d: -f3)
log_success "组 '$groupname' 创建成功 (GID: $new_gid)"
else
log_error "创建组失败"
fi
show_result
}
# 删除组
delete_group() {
log_title "删除组"
echo "系统中的组:"
getent group | awk -F: '$3 >= 1000 {print $1 " (GID: " $3 ")"}' | column
local groupname
read -p "请输入要删除的组名: " groupname < /dev/tty
groupname=$(echo "$groupname" | xargs)
if [ -z "$groupname" ]; then
log_error "组名不能为空"
return 1
fi
if ! group_exists "$groupname"; then
log_error "组 '$groupname' 不存在"
return 1
fi
# 检查是否有用户以此为主组
local users_in_group=$(getent group "$groupname" | cut -d: -f4)
local primary_users=$(awk -F: -v gid="$(getent group "$groupname" | cut -d: -f3)" '$4 == gid {print $1}' /etc/passwd)
if [ -n "$primary_users" ]; then
log_warn "以下用户以此组为主组:"
echo "$primary_users"
log_error "无法删除,请先修改这些用户的主组"
return 1
fi
if [ -n "$users_in_group" ]; then
log_warn "组中包含以下用户: $users_in_group"
fi
if ! confirm_action "确认删除组 '$groupname'?"; then
log_info "已取消删除操作"
return 0
fi
if groupdel "$groupname" 2>/dev/null; then
log_success "组 '$groupname' 已删除"
else
log_error "删除组失败"
fi
show_result
}
# ============================================================================
# 列表显示功能
# ============================================================================
# 简单列出普通用户
list_normal_users_simple() {
echo -e "${BLUE}系统普通用户:${NC}"
getent passwd | awk -F: '$3 >= 1000 && $3 < 65534 {printf " %s (UID: %s)\n", $1, $3}'
echo
}
# 列出所有用户
list_all_users() {
log_title "用户列表"
echo -e "${CYAN}${BOLD}普通用户 (UID >= 1000):${NC}"
printf "%-20s %-8s %-15s %-20s %-30s\n" "用户名" "UID" "主组" "Shell" "主目录"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
getent passwd | awk -F: '$3 >= 1000 && $3 < 65534 {print $0}' | while IFS=: read -r username _ uid gid _ homedir shell; do
local primary_group=$(getent group "$gid" | cut -d: -f1)
printf "%-20s %-8s %-15s %-20s %-30s\n" "$username" "$uid" "$primary_group" "$shell" "$homedir"
done
echo
local user_count=$(getent passwd | awk -F: '$3 >= 1000 && $3 < 65534 {count++} END {print count}')
log_info "普通用户总数: $user_count"
pause_for_view
}
# 列出所有用户详细信息
list_all_users_detailed() {
log_title "所有用户详细信息"
getent passwd | awk -F: '$3 >= 1000 && $3 < 65534 {print $1}' | while read -r username; do
show_user_details "$username"
echo
done
}
# 查看用户详细信息
view_user_info() {
log_title "查看用户详细信息"
local username
read -p "请输入用户名 (留空查看所有用户): " username < /dev/tty
username=$(echo "$username" | xargs)
if [ -z "$username" ]; then
list_all_users_detailed
else
if ! user_exists "$username"; then
log_error "用户 '$username' 不存在"
return 1
fi
show_user_details "$username"
fi
pause_for_view
}
# 显示单个用户的详细信息
show_user_details() {
local username="$1"
echo
echo -e "${CYAN}${BOLD}用户详细信息: $username${NC}"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
local uid=$(get_user_uid "$username")
local gid=$(id -g "$username")
local primary_group=$(get_user_primary_group "$username")
local all_groups=$(get_user_groups "$username")
local homedir=$(getent passwd "$username" | cut -d: -f6)
local shell=$(getent passwd "$username" | cut -d: -f7)
local gecos=$(getent passwd "$username" | cut -d: -f5)
echo -e "${GREEN}UID:${NC} $uid"
echo -e "${GREEN}GID:${NC} $gid"
echo -e "${GREEN}主组:${NC} $primary_group"
echo -e "${GREEN}所有组:${NC} $all_groups"
echo -e "${GREEN}主目录:${NC} $homedir"
echo -e "${GREEN}Shell:${NC} $shell"
[ -n "$gecos" ] && echo -e "${GREEN}备注:${NC} $gecos"
# 检查主目录是否存在
if [ -d "$homedir" ]; then
local home_size=$(du -sh "$homedir" 2>/dev/null | cut -f1)
echo -e "${GREEN}主目录大小:${NC} $home_size"
else
echo -e "${YELLOW}主目录不存在${NC}"
fi
# 检查用户状态
if passwd -S "$username" 2>/dev/null | grep -q " L "; then
echo -e "${GREEN}账户状态:${NC} ${RED}已锁定${NC}"
else
echo -e "${GREEN}账户状态:${NC} ${GREEN}正常${NC}"
fi
# 显示最后登录时间
local last_login=$(lastlog -u "$username" 2>/dev/null | tail -n 1)
if [ -n "$last_login" ]; then
echo -e "${GREEN}最后登录:${NC} $last_login"
fi
# 检查sudo权限
if user_in_group "$username" "$SUDO_GROUP"; then
echo -e "${GREEN}Sudo权限:${NC} ${GREEN}${NC}"
else
echo -e "${GREEN}Sudo权限:${NC}"
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}
# 列出所有组
list_all_groups() {
log_title "组列表"
echo -e "${CYAN}${BOLD}系统组 (GID >= 1000):${NC}"
printf "%-25s %-8s %-50s\n" "组名" "GID" "成员"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
getent group | awk -F: '$3 >= 1000 {print $0}' | while IFS=: read -r groupname _ gid members; do
# 查找以此组为主组的用户
local primary_users=$(awk -F: -v gid="$gid" '$4 == gid {printf "%s,", $1}' /etc/passwd | sed 's/,$//')
# 合并主组用户和附加组成员
local all_members="$members"
if [ -n "$primary_users" ]; then
if [ -n "$all_members" ]; then
all_members="$primary_users,$all_members"
else
all_members="$primary_users"
fi
fi
printf "%-25s %-8s %-50s\n" "$groupname" "$gid" "$all_members"
done
echo
local group_count=$(getent group | awk -F: '$3 >= 1000 {count++} END {print count}')
log_info "组总数: $group_count"
pause_for_view
}
# 查看组详细信息
view_group_info() {
log_title "查看组详细信息"
local groupname
read -p "请输入组名: " groupname < /dev/tty
groupname=$(echo "$groupname" | xargs)
if [ -z "$groupname" ]; then
log_error "组名不能为空"
return 1
fi
if ! group_exists "$groupname"; then
log_error "组 '$groupname' 不存在"
return 1
fi
show_group_details "$groupname"
pause_for_view
}
# 显示单个组的详细信息
show_group_details() {
local groupname="$1"
echo
echo -e "${CYAN}${BOLD}组详细信息: $groupname${NC}"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
local gid=$(getent group "$groupname" | cut -d: -f3)
local members=$(getent group "$groupname" | cut -d: -f4)
echo -e "${GREEN}GID:${NC} $gid"
# 查找以此组为主组的用户
local primary_users=$(awk -F: -v gid="$gid" '$4 == gid {print $1}' /etc/passwd | tr '\n' ',' | sed 's/,$//')
if [ -n "$primary_users" ]; then
echo -e "${GREEN}主组用户:${NC} $primary_users"
else
echo -e "${GREEN}主组用户:${NC}"
fi
if [ -n "$members" ]; then
echo -e "${GREEN}附加成员:${NC} $members"
else
echo -e "${GREEN}附加成员:${NC}"
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}
# ============================================================================
# 菜单系统
# ============================================================================
# 显示主菜单
show_main_menu() {
clear
echo -e "${CYAN}${BOLD}"
echo "╔════════════════════════════════════════════════════════════╗"
echo "║ Linux 用户和组管理工具 (增强版) ║"
echo "╚════════════════════════════════════════════════════════════╝"
echo -e "${NC}"
echo -e "${BLUE}系统信息:${NC} $OS_NAME $OS_VERSION ($ARCH_NAME)"
echo
echo -e "${YELLOW}${BOLD}用户管理:${NC}"
echo " 1) 添加用户"
echo " 2) 删除用户"
echo " 3) 修改用户信息"
echo " 4) 修改用户密码"
echo " 5) 查看用户详细信息"
echo " 6) 列出所有用户"
echo
echo -e "${YELLOW}${BOLD}组管理:${NC}"
echo " 7) 添加组"
echo " 8) 删除组"
echo " 9) 列出所有组"
echo " 10) 查看组详细信息"
echo
echo -e "${YELLOW}${BOLD}用户组关系:${NC}"
echo " 11) 管理用户组成员"
echo
echo -e "${YELLOW}${BOLD}其他:${NC}"
echo " 0) 退出"
echo
}
# 主菜单循环
main_menu() {
while true; do
show_main_menu
local choice
read -p "请选择 [0-11]: " choice < /dev/tty
case $choice in
1)
add_user
;;
2)
delete_user
;;
3)
modify_user
;;
4)
change_user_password
;;
5)
view_user_info
;;
6)
list_all_users
;;
7)
add_group
;;
8)
delete_group
;;
9)
list_all_groups
;;
10)
view_group_info
;;
11)
manage_user_groups
;;
0)
echo
log_success "感谢使用,再见!"
exit 0
;;
*)
log_error "无效的选择,请重新输入"
sleep 1
;;
esac
done
}
# ============================================================================
# 主函数
# ============================================================================
main() {
# 初始化系统
init_system
# 显示欢迎信息
echo
log_success "系统初始化完成"
sleep 1
# 进入主菜单
main_menu
}
# 执行主函数
main "$@"