前言
“最小权限原则"落地的第一站就是账号体系:日常用普通用户 + 按需 sudo,而不是人人 root。这篇把用户、组、sudo 的管理一次讲全。
一、用户与组的本质
一切都在这三个文件里:
/etc/passwd # 用户账本
/etc/shadow # 密码哈希(只有 root 可读)
/etc/group # 组账本
# passwd 每行七段
zy:x:1000:1000::/home/zy:/bin/bash
│ │ │ │ │ │ └ 登录 shell
│ │ │ │ │ └ 家目录
│ │ │ │ └ 备注(GECOS)
│ │ │ └ 主组 GID
│ │ └ UID(<1000 多为系统账号)
│ └ 密码占位(真密码在 shadow)
└ 用户名
# 快速查某个用户
id zy
# uid=1000(zy) gid=1000(zy) groups=1000(zy),10(wheel),994(docker)
二、用户管理命令
# 创建(RHEL 系默认建同名主组)
useradd -m -s /bin/bash -c "运维-zy" alice # -m 建家目录
useradd -r -s /sbin/nologin deploy # -r 系统账号(跑服务用, 不能登录)
# 设置/改密码
passwd alice # 交互式
echo "alice:Str0ngPass" | chpasswd # 脚本式
# 修改属性
usermod -aG docker,wheel alice # 追加附加组(-aG 别写成 -G, 会覆盖!)
usermod -L alice # 锁定账号(禁登录)
usermod -U alice # 解锁
usermod -s /sbin/nologin alice # 换 shell(禁交互登录)
# 删除
userdel -r alice # -r 连家目录和邮箱一起删
# 查看登录情况
last | head
who / w # 当前在线
给服务建运行用户的惯例:
useradd -r -s /sbin/nologin -d /opt/myapp myapp
# 之后 systemd unit 里 User=myapp, chown -R myapp:myapp /opt/myapp
三、组管理
groupadd developers
groupmod -n devs developers # 改名
groupdel devs
gpasswd -a alice developers # 加成员
gpasswd -d alice developers # 移除成员
# 临时切换主组(新建文件属组生效)
newgrp developers
# 组密码极少用; 现代用法基本是: 附加组 + sudo
组的典型玩法——目录共享(回顾权限篇):
groupadd devops
usermod -aG devops alice; usermod -aG devops bob
mkdir -p /data/share && chgrp devops /data/share
chmod 2770 /data/share # SGID: 新文件自动继承 devops 组
四、sudo:受控的提权
su - 是"整个 root 身份交出去”,sudo 是"按规则放行特定命令并留审计日志"。
# 编辑 sudoers 永远用 visudo(保存前做语法检查, 防止把自己锁死!)
visudo
# 或子文件(推荐, 便于管理)
visudo -f /etc/sudoers.d/deploy
规则语法:
谁 在哪台主机=(以谁的身份) 可以跑什么命令
实用规则示例:
# wheel 组成员可全权 sudo(RHEL 默认存在)
%wheel ALL=(ALL) ALL
# 免密 sudo(自动化脚本常用, 但要评估风险)
zy ALL=(ALL) NOPASSWD: ALL
# 只允许跑特定命令
deploy ALL=(root) /usr/bin/systemctl restart myapp, \
/usr/bin/systemctl status myapp
# 只允许以 app 用户身份执行(不给 root!)
tester ALL=(myapp) NOPASSWD: /opt/myapp/bin/test.sh
# 组规则 + 排除法(慎用, 可被绕过, 尽量白名单)
%devs ALL=(ALL) ALL, !/usr/bin/su, !/usr/sbin/visudo
sudo 的高级用法:
sudo -l # 列出我当前能跑哪些命令
sudo -u myapp ./run.sh # 以其他用户执行(不只 root)
sudo -i # 完整 root 登录环境(≈su -)
sudo !! # 以 sudo 重跑上一条命令(万能急救)
# 审计: 谁在什么时候跑了什么
journalctl -t sudo | tail
grep sudo /var/log/secure | tail
五、密码策略
chage -l alice # 查看策略
# 密码 90 天过期, 提前 7 天警告, 5 天内不能改第二次
chage -M 90 -W 7 -m 5 alice
chage -d 0 alice # 强制下次登录改密码
chage -E 2025-12-31 contractor # 账号到期自动禁用(外包神器)
# 全局策略(login.defs)
sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 90/' /etc/login.defs
# 密码复杂度(pam pwquality)
# /etc/security/pwquality.conf
minlen = 12
minclass = 3 # 至少3类字符
六、账号健康巡检
# 1. 能登录的系统账号(危险! 应为空, 至少无 shell)
awk -F: '$3<1000 && $7!~/(nologin|false)/ {print $1, $7}' /etc/passwd
# 2. 空密码账号(必须为空!)
awk -F: '($2==""){print $1}' /etc/shadow
# 3. UID=0 的账号(应只有 root)
awk -F: '$3==0 {print $1}' /etc/passwd
# 4. 90天未登录的账号(僵尸候选)
lastlog -b 90 | grep -v "Never logged in" | awk 'NR>1 && $2!="" {print $1}'
# 5. sudoers 里的 NOPASSWD 盘点
grep -rn NOPASSWD /etc/sudoers /etc/sudoers.d/ 2>/dev/null
把这几条丢进巡检脚本(见我那篇 Bash 巡检),每周自动跑。
七、实战场景
给新同事开账号(标准动作):
USERNAME=alice
useradd -m -s /bin/bash $USERNAME
echo "$USERNAME:初始密码" | chpasswd
chage -d 0 $USERNAME # 首登强制改密
usermod -aG developers $USERNAME # 业务组
# 需要提权时: visudo 加白名单, 而不是塞进 wheel
回收离职账号:
usermod -L alice # 1. 先锁定(立即失效)
usermod -s /sbin/nologin alice # 2. 禁 shell(双保险)
crontab -r -u alice 2>/dev/null # 3. 清定时任务
# 4. 归档家目录后删除(保留审计期数据)
tar -czf /backup/userdata/alice-$(date +%F).tar.gz /home/alice
userdel -r alice
grep -rn alice /etc/sudoers.d/ # 5. 清 sudoers 残留
小结
| 任务 | 命令 |
|---|---|
| 建用户 | useradd -m -s /bin/bash |
| 调组 | usermod -aG(记得 -a) |
| 授权 | visudo -f /etc/sudoers.d/xx 白名单 |
| 审计 | journalctl -t sudo |
| 巡检 | UID=0 / 空密码 / 可登录系统账号 |
| 服务账号 | -r -s /sbin/nologin |
本文是「Linux 基础」系列第 7 篇。