Appearance
用户与组
Linux 的登录认证、文件权限、服务进程身份都围绕用户和组展开。排查权限问题时,需要同时确认账号是否存在、属于哪些组、使用什么 Shell、以及进程以什么身份运行。
一、UID 和 GID
Linux 内核识别的是数字 ID,不是用户名。用户名只是给人看的标签,权限判断时看的是 UID 和 GID。
| 名称 | 含义 |
|---|---|
| UID | 用户 ID。0 是 root,拥有完整权限 |
| GID | 主组 ID。每个用户属于一个主组 |
| 附加组 | 用户额外加入的其他组,一个用户可同时属于多个组 |
查看当前用户身份:
bash
whoami # 当前用户名
id # uid、gid、所有附加组
groups # 所属组列表排查权限问题看 id 比看 whoami 更有价值。一个用户能否访问某个文件,取决于他的 uid 和所有 gid,光看用户名判断不了完整权限。
文件系统中记录的 owner 和 group 本质上是 UID 和 GID 的数字。两台机器之间复制文件时,如果目标机器上相同 UID 对应的用户不同,就会出现文件属于"不认识的人"的情况。比如源机器上 UID 1001 是 nginx,目标机器上 UID 1001 是 deploy,文件拷过去后 ls -l 会显示 owner 是 deploy。
二、用户和组的关键文件
Linux 的用户和组信息分布在几个文件中。直接 cat 这些文件也行,但用 getent 更可靠——它会走系统名称服务(NSS),LDAP、NIS 等集中认证环境也能正确查询。
| 文件 | 内容 |
|---|---|
/etc/passwd | 用户名、UID、GID、家目录、Shell |
/etc/shadow | 密码哈希、密码过期策略 |
/etc/group | 组名、GID、组成员 |
/etc/gshadow | 组密码(很少用) |
bash
getent passwd nginx
getent group wheel/etc/passwd 一行拆解:
root:x:0:0:root:/root:/bin/bash| 字段 | 值 | 说明 |
|---|---|---|
| 用户名 | root | 登录时使用的名称 |
| 密码占位 | x | 密码哈希实际存在 /etc/shadow 中 |
| UID | 0 | 用户 ID |
| GID | 0 | 主组 ID |
| GECOS | root | 注释字段,通常放全名或说明 |
| 家目录 | /root | 登录后的起始目录 |
| Shell | /bin/bash | 登录后启动的 Shell |
三、创建用户
bash
useradd app # 创建用户
passwd app # 设置密码useradd 的默认行为受 /etc/login.defs 和 /etc/default/useradd 两个配置影响——是否创建家目录、默认 Shell、UID 范围等,不同发行版默认值不完全一样。生产上创建服务账号时,关键参数显式指定更保险。
指定家目录和 Shell:
bash
useradd -m -d /home/deploy -s /bin/bash deploy创建不需要登录的服务用户(系统用户):
bash
useradd -r -s /sbin/nologin nginx-r 创建系统用户,分配的 UID 通常在系统用户范围内(不同发行版范围不同)。/sbin/nologin 或 /usr/sbin/nologin 作为 Shell 时,该用户不能登录系统,但服务进程仍然可以用它运行。
四、修改和删除用户
bash
usermod -aG wheel deploy # 追加到 wheel 附加组
usermod -s /bin/bash deploy # 修改登录 Shell
usermod -L deploy # 锁定用户(禁止登录)
usermod -U deploy # 解锁用户usermod -G 的正常行为是替换所有附加组。要追加而不是替换,必须加 -a。这条很容易出错——把用户加到 docker 组或 sudo 组时漏了 -a,用户就会从原来的所有附加组中被移除。
删除用户:
bash
userdel app
userdel -r app # 同时删除家目录和邮件目录正式环境下删除用户前,通常先锁定再看一段时间,确认没有遗留的定时任务或服务依赖这个账号。
bash
usermod -L olduser
chage -E 0 olduser # 将账号过期时间设为 1970-01-01,立即失效五、su 和 sudo
su 切换用户身份:
bash
su - appsu -(带横杠)会加载目标用户的完整登录环境,包括环境变量、PATH、工作目录等。su app 不带横杠只切换用户身份,不切换环境,执行时会继承原来用户的 PATH 和当前目录。
sudo 以其他用户身份执行单条命令:
bash
sudo systemctl restart nginxsudo 的配置文件通过 visudo 编辑:
bash
visudovisudo 在保存前会检查语法,防止写错后 sudo 全部不可用。直接手动编辑 /etc/sudoers 有风险。
RHEL 系的管理员组通常叫 wheel,Ubuntu 叫 sudo。把一个用户加入管理员组:
bash
usermod -aG wheel deploy # RHEL 系
usermod -aG sudo deploy # Ubuntu / Debiansudoers 中针对特定命令的授权写法:
sudoers
deploy ALL=(root) /usr/bin/systemctl restart nginx字段从左到右:(1)授权哪个用户或组(组前面加 %);(2)从哪些主机登录时生效;(3)以谁的身份执行;(4)允许执行的具体命令,须写绝对路径。
sudo 权限的粒度越细越好。所有人配成 ALL=(ALL) NOPASSWD:ALL 在运维上风险偏高——事后看 sudo 日志,无法区分是谁执行了高危命令。
六、查看登录状态
bash
w # 当前有哪些用户登录,在做什么
who # 简化的在线用户列表
last # 历史登录记录(读取 /var/log/wtmp)
lastb # 失败登录记录(读取 /var/log/btmp)SSH 暴露在公网时 lastb 的输出通常很长。暴力尝试多的时候,改端口只能减少日志噪音,真正的安全依赖仍然是密钥认证、限制来源 IP 或走堡垒机统一入口。