定期清理过期账户需“判得准、锁得稳、删得慎、留得清”,即三条件同时满足(uid≥1000、90天无登录、shell为nologin/false且shadow密码字段非*或!)才识别为待清理账户;先用usermod -s /usr/sbin/nologin冻结,观察48小时日志无异常后,再userdel -r删除,并同步清理sudo、cron等权限残留,全程记录结构化审计日志。

定期清理过期账户不是删掉就完事,关键在“判得准、锁得稳、删得慎、留得清”。权限变更追踪则必须与清理动作绑定,否则加固效果不可验证、不可回溯。
怎么识别真正该清理的过期账户
不能只看登录时间,要三条件同时满足才纳入清理范围:
- UID ≥ 1000(排除 root、syslog、sshd 等系统服务账号)
- 90 天内无成功登录(用 lastlog -b 90,比 last 更可靠)
- shell 为 /sbin/nologin 或 /bin/false,且 /etc/shadow 中密码字段不是 * 或 !(说明曾有有效密码)
快速筛查命令:
lastlog -b 90 | awk '$1 !~ /^(root|sync|shutdown|halt|operator|nobody|.*daemon)/ && $5 != "Never" {print $1}' | while read u; do [ $(id -u "$u" 2>/dev/null) -ge 1000 ] && grep -qE "^$u:.*nologin|false$" /etc/passwd && [ "$(awk -F: -v u="$u" '$1==u {print $2}' /etc/shadow)" != "*" ] && echo "$u"; done
先冻结,再观察,最后处置
直接删除风险高。标准操作分两阶段,中间至少保留 48 小时观察窗口:
- 冻结登录能力:sudo usermod -s /usr/sbin/nologin username(比 passwd -l 更彻底,防 SSH 密钥绕过)
- 同步清理权限残留:sudo rm -f /etc/sudoers.d/username、sudo crontab -u username -r、sudo systemctl --user disable --now *.service
- 观察日志确认无影响:journalctl -u systemd-logind -S "2 days ago" | grep "$username" 和 grep "Invalid user $username" /var/log/auth.log
- 确认无误后,再执行 sudo userdel -r username(-r 才删家目录;新手建议先手动检查 /home/username 和 /var/spool/mail/username)
权限变更必须自动记录与追踪
每次冻结或删除,都应生成结构化审计日志,包含时间、操作类型、用户名、最后登录时间、执行人:
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
logger -t user-cleanup "DISABLED: $username (last login: $(lastlog -u $username 2>/dev/null | tail -1 | awk '{print $5,$6,$7}')) by $(whoami)"
同时将操作写入独立日志文件,例如:
echo "$(date '+%F %T'): DISABLED $username (last login: $(lastlog -u $username 2>/dev/null | tail -1 | awk '{print $5,$6,$7}'))" >> /var/log/user_cleanup.log
每月归档一次日志,并保留至少 180 天,用于安全审计和事件复盘。
清理后必须收口剩余权限
账户删了,权限未必跟着消失。需同步做四件事:
- 检查并清理 sudo 授权:删掉 /etc/sudoers 中孤立的 ALL=(ALL) ALL 行,改用 /etc/sudoers.d/ 下按组白名单授权
- 确认 SSH 配置:PermitRootLogin no 和 PasswordAuthentication no 已启用
- 扫描异常 SUID/SGID 文件:find / -perm -4000 -o -perm -2000 2>/dev/null | xargs -r stat -c "%U %a %n" 2>/dev/null | awk '$1 !~ /^(root|bin|daemon|sys)$/ {print}'
- 季度清理空组:getent group | awk -F: '$4 == "" && $3 >= 1000 {print $1}' | xargs -r groupdel










