Shell脚本for循环多条件实现:macOS清理admin组非白名单用户
macOS admin组多余用户清理脚本问题修正
需求说明
需要在macOS系统中对比两个用户组的成员,将admin组内不存在于newadmin组的用户移除。
初版脚本问题分析
最初编写的脚本如下:
newadmins=$(dscl . -read Groups/newadmin GroupMembership | cut -c 18-) adminUsers=$(dscl . -read Groups/admin GroupMembership | cut -c 18-) for (user in $adminUsers && ! user in $newadmins) do dseditgroup -o edit -d $user -t user admin if [ $? = 0 ]; then echo "Removed user $user from admin group"; fi else echo "Admin user $user left alone" fi done
存在的问题如下:
- 循环语法错误:Shell原生for循环不支持
for (user in $数组 && 过滤条件)这种类其他编程语言的写法,for循环仅能遍历列表元素,过滤逻辑需要在循环内部通过if语句实现 - 分支结构错误:do代码块内没有配对的if就直接写else,不符合Shell的语法规范
- 成员提取方式鲁棒性差:用
cut -c 18-按固定字符偏移截取成员列表,若dscl输出的前缀长度变化会导致提取结果出错
可运行脚本修正
后续调整的脚本已经基本实现需求,但存在一个大小写不匹配的问题:变量定义为全大写的DEFUNCT_ADMIN_USER,但dseditgroup命令中用了小写的${defunct_admin_user},Shell变量大小写敏感,会导致命令执行失败。
修正后的完整脚本如下:
NEW_ADMIN_USERS=$(dscl . -read Groups/newadmin GroupMembership | cut -d ' ' -f 2-) ADMIN_USERS=$(dscl . -read Groups/admin GroupMembership | cut -d ' ' -f 2-) DEFUNCT_ADMIN_USERS=$(grep -vxFf <(echo ${NEW_ADMIN_USERS} | tr ' ' '\n') <(echo ${ADMIN_USERS} | tr ' ' '\n')) for DEFUNCT_ADMIN_USER in ${DEFUNCT_ADMIN_USERS} do if dseditgroup -o edit -d ${DEFUNCT_ADMIN_USER} -t user admin then echo "Removed user ${DEFUNCT_ADMIN_USER} from admin group" else echo "Admin user ${DEFUNCT_ADMIN_USER} left alone" fi done
内容的提问来源于stack exchange,提问作者Duetschpire
相关产品推荐
相关产品推荐

