5671 字
28 分钟
Linux基础(5):Linux用户与权限管理体系详解

前言#

Linux是一个多用户、多任务的操作系统,用户与权限管理是Linux系统安全的核心基石。所有系统操作、文件访问和进程运行都基于用户身份和权限控制。深入理解用户分类、UID/GID机制、sudo权限和文件权限体系,是保障系统安全、规范用户行为的必备技能。

本文内容适用于 Ubuntu、CentOS 9 Stream、银河麒麟 和 openEuler 等所有主流Linux发行版。 ::

一、用户与组的基础概念#

1.1 UID与GID:用户和组的唯一标识#

Linux系统不通过用户名识别用户,而是通过数字ID来识别:

  • UID (User ID):用户唯一标识号,每个用户拥有一个全局唯一的UID。
  • GID (Group ID):用户组唯一标识号,每个组拥有一个全局唯一的GID。
NOTE核心配置文件
  • 用户名和UID的映射关系存储在 [/etc/passwd] 密级文件中。
  • 用户密码哈希值存储在处于极高权限读写控制的 [/etc/shadow] 文件中。
  • 组名和GID的映射关系存储在 /etc/group 文件中。 ::

1.2 /etc/passwd:揭秘用户账户的核心档案#

在 Linux 中,所有用户的基本信息(除了密码的真实哈希值)都以明文形式公开存放在 /etc/passwd 文件中。理解这个文件的结构,是排查用户问题的基本功。

我们可以使用 cat 或 head 查看其中的内容:

Terminal
[root@server ~]# head -n 3 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
testuser:x:1000:1000:Test Account:/home/testuser:/bin/bash

每一行代表一个用户,通过冒号 : 分隔成了 7 个关键字段。以 testuser:x:1000:1000:Test Account:/home/testuser:/bin/bash 为例,字段含义拆解如下:

字段序号示例内容含义解析
1testuser用户名。登录时使用的账号名称。
2x密码占位符。早期的确在这里存密码,后来为了安全,密码被移到了权限极严的 /etc/shadow 中,这里统一用 x 占位。
31000UID (用户ID)。系统内部真正用来识别用户的数字标识。
41000GID (主组ID)。用户所属的主组的数字标识,对应 /etc/group 中的记录。
5Test Account用户信息说明。通常是用户的全名、联系方式等备注信息(可选字段,可为空)。
6/home/testuser家目录路径。用户登录成功后,默认进入的工作目录。
7/bin/bash默认 Shell。用户登录后分配的命令解释器。如果是 /sbin/nologin 或 /bin/false,则代表该用户被禁止登录系统(通常用于系统服务账号)。

1.3 Linux用户分类#

根据UID范围和权限不同,Linux用户分为三类:

用户类型UID范围说明
超级用户 (root)0拥有系统最高权限,可以执行任何操作,不受权限限制。
系统用户1-999系统服务运行所需的用户,默认禁止登录Shell,如 nginx、mysql。
普通用户1000+管理员创建的普通登录用户,权限受限,仅能操作自己家目录和授权资源。

[!WARNING] 发行版差异注意 Ubuntu 22.04 LTS 及更新的发行版,普通用户UID从 1000 开始(早期部分版本为 500+)。跨发行版迁移数据时需警惕UID错位导致权限丢失的问题。

1.4 用户组的概念#

用户组是具有相同权限的用户集合,用于简化权限管理:

  • 主组 (primary group):每个用户必须且只能有一个主组,创建用户时默认创建同名主组。
  • 附加组 (supplementary group):用户可以加入0个或多个附加组,继承附加组的所有权限。

二、用户管理核心命令(增删改查完全指南)#

在日常运维中,员工入职、转岗、离职都对应着账号的生命周期管理。以下所有增删改查操作,均需要 root 权限或通过 sudo 执行。

2.1 创建与删除用户:useradd & userdel#

创建用户 (useradd)#

创建新用户账户是系统初始化的第一步。不同的场景需要搭配不同的参数。

常用参数速查表:

参数作用说明常见场景
-m自动创建用户的家目录(/home/用户名)为真人创建账号时必加
-s指定用户的默认 Shell 程序正常登录指定 /bin/bash,禁止登录指定 /sbin/nologin
-g指定用户的主组(只能有一个)-g developers
-G指定用户的附加组(可多个,逗号分隔)-G wheel,docker
-r创建系统虚拟账户(UID小于1000)创建用来运行 Nginx/MySQL 的非登录账号
WARNING安全警示

为真人创建登录账户时,务必携带 -m 参数以生成家目录(/home/用户名)。否则用户后续通过 SSH 登录时,将面临无法存放 SSH 公钥(.ssh 目录缺失)、环境配置文件(如 .bashrc)丢失等严重问题。 ::

Terminal
# 1. 常规操作:创建普通用户,自动创建家目录,并指定 bash 为解释器(最常用)
useradd -m -s /bin/bash testuser
# 2. 复合操作:创建用户时,直接指定它的主组(-g)和多个附加组(-G)
# 场景:新入职开发,属于 developers 组,同时需要 nginx 和 wheel 的权限
useradd -m -s /bin/bash -g developers -G wheel,nginx devuser
# 3. 创建系统虚拟用户(极其重要)
# 场景:为了运行 Nginx 或 MySQL 建立的账号。
# 必须加上 -r(系统账号)、-s /sbin/nologin(禁止登录)、不需要 -m(不需要家目录)
useradd -r -s /sbin/nologin mysql

删除用户 (userdel)#

员工离职时,妥善删除账号是必经流程,删除分为“软删除”和“硬删除”。

常用参数速查表:

参数作用说明常见场景
(无)仅删除用户账号信息,保留家目录员工离职,账号回收但需要保留其工作文件交接
-r彻底删除用户,连同家目录和邮件池一并删除清理测试账号、清理已完成交接的离职人员垃圾
Terminal
# 1. 软删除:仅删除系统账号,但保留 /home/testuser 家目录里的数据
# 场景:员工离职,账号回收,但他的工作文件需要留给主管审查交接
userdel testuser
# 2. 硬删除:彻底删除账号,并强制删掉对应的家目录和本地邮件池
# 场景:交接完毕,彻底清理系统垃圾
userdel -r testuser

2.2 密码安全生命周期:passwd#

passwd 不仅仅是用来“改密码”的,它更是系统管理员控制账户安全周期的利器。

常用参数速查表:

参数作用说明常见场景
-e强制密码过期 (expire)统一建号后,要求新员工首次登录必须重置密码
-l锁定账户 (lock)发现账号异地登录或被爆破,紧急冻结禁止密码登录
-u解锁账户 (unlock)解除锁定状态
-S查看状态 (Status)查看某账号当前是否被锁定、密码过期时间等信息
-d删除密码 (delete)极度危险,允许账号无密码登录,绝对禁止使用!
Terminal
# 1. 修改密码:root 可以改任何人的,普通用户直接敲 passwd 只能改自己的
passwd testuser
# 2. 强制下次登录重置密码(极度推荐!)
# 场景:管理员统一为新员工建号并设置初始密码(如 123456),
# 执行此命令后,新员工第一次登录必须马上修改密码,免去安全隐患
passwd -e testuser
# 3. 锁定异常账户(防爆破)
# 场景:发现 testuser 正在被频繁爆破密码,紧急锁定,让他无法用密码登录
passwd -l testuser
# 4. 解锁账户
passwd -u testuser
# 5. 查看账户的密码状态(LK=锁定,PS=正常,NP=无密码)
passwd -S testuser
CAUTION危险操作

绝对禁止使用 passwd -d 用户名 清空密码。此举将极大降低系统防御等级,造成任意人员零门槛提权隐患! ::

2.3 修改用户属性:usermod#

当员工转岗,或者需要临时提权、封禁时,usermod 是修改已存在用户属性的神器。

常用参数速查表:

参数作用说明常见场景
-aG追加用户到附加组 (Append Group)提权必备:把用户加到 wheel 或 docker 组
-s修改默认 Shell封禁账号登录权限时改为 /sbin/nologin
-l修改登录名 (Login)员工改名或转正平滑修改账号名,不影响底层 UID 和数据
-g修改主组改变用户的初始主组(不推荐频繁操作主组)
Terminal
# 1. 将用户追加到新的附加组
# 场景:让普通用户获得 sudo 提权资格(CentOS系加到 wheel,Ubuntu系加到 sudo)
usermod -aG wheel testuser
# 2. 封禁登录:修改用户的默认 Shell
# 场景:外包人员项目结束,保留数据但不允许再登录系统
usermod -s /sbin/nologin testuser
# 3. 账号更名:平滑变更为新名字,原有的 UID、GID、家目录统统不变
# 场景:外包转正,从 v-zhangsan 改名为 zhangsan
usermod -l newuser olduser
# 4. 修改用户的主组(很少用,通常只改附加组)
usermod -g newgroup testuser
TIP血泪教训

在赋予用户新的附加组时,必须且永远使用 -aG(Append + Group)。如果漏写 a(仅使用 -G),将会直接清空并覆盖该用户原有的所有附加组!无数新手因为漏掉一个 a 导致用户丢失了原本的文件访问权限。 ::

2.4 用户组的创建与修改:groupadd 等#

权限控制的基石是 RBAC(基于角色的访问控制),在 Linux 中体现为**“组管理”**。我们应该先建组、给组赋权,再把用户拉进组里。

组管理核心命令与参数速查表:

命令/参数作用说明常见场景
groupadd创建新的用户组groupadd developers
groupadd -r创建系统虚拟用户组创建分配给 Nginx 等后台服务的组,GID 会小于 1000
groupmod -n修改用户组的名称 (New Name)公司部门改名,将 dev 组改名为 rd 组
groupdel删除用户组清理废弃的权限组。注意:如果该组是某人的主组,则无法删除
gpasswd -a把用户加入组 (Add)相当于 usermod -aG,把 testuser 加进 wheel 组
gpasswd -d把用户移出组 (Delete)剥夺权限必备:将离职或转岗员工踢出核心运维组
Terminal
# 1. 创建一个新用户组(如研发组、运维组)
groupadd developers
# 2. 创建系统级的虚拟用户组(配合系统虚拟账户使用)
groupadd -r mysql
# 3. 修改组名(将 developers 平滑变更为 devops,原有的 GID 不变)
groupmod -n devops developers
# 4. 将用户移出某个附加组(使用 gpasswd 命令)
# 场景:实习生结束轮岗,剥夺他的高级运维权限(移出 wheel 组)
gpasswd -d testuser wheel
# 5. 删除用户组
# 注意:如果要删除的组是某个用户的主组,则必须先删用户或修改其主组,否则无法删除
groupdel devops

2.5 查看与切换身份 (su 与查询命令)#

日常排错时,我们需要经常查看用户身份,或者切换身份去验证权限。这里面的参数携带尤为关键。

切换身份参数速查表 (su):

参数组合执行逻辑核心特点与区别
su - 用户名完全切换(Login Shell)强烈推荐。会完全读取目标用户的环境变量(如 .bashrc、.profile),并且当前目录直接切换到目标用户的家目录,就像重新登录了一样。
su 用户名非完全切换(Non-login Shell)极度不推荐。只切换了身份,但保留上一个用户的环境变量和当前所在路径。经常导致命令找不到、权限错乱等各种诡异问题。
su - 用户名 -c "命令"免切身份执行单次命令运维写脚本或配置 crontab 定时任务时的绝佳伴侣,不需要真的切进去。
Terminal
# 1. 查看指定用户的身份信息(UID、主组、所有附加组)
# 场景:排查某人为什么打不开某个文件,先看他在不在对应的组里
id testuser
# 2. 抓内鬼:查看当前有哪些人在线,正在执行什么命令
w
who
# 3. 切换身份(切记区分带减号和不带减号的区别)
# 【强烈推荐】完全切换(需要密码,且重新加载该用户的完整环境变量,像重新登录一样)
su - testuser
# 【不推荐】仅切换身份(环境变量仍残留上一个用户的配置,极易引发命令找不到、路径错乱)
8 collapsed lines
su testuser
# 4. 免切用户执行一次性指令(运维最爱)
# 场景:在 root 的定时任务 (crontab) 中,以 testuser 的身份去跑脚本
su - testuser -c "sh /home/testuser/backup.sh"
# 5. 企业绝活:批量枚举系统所有可登录的真人账户(UID >= 1000 且 Shell 正常)
awk -F: '$3 >= 1000 && $7 != "/sbin/nologin" && $7 != "/bin/false" {print $1}' /etc/passwd

三、sudo 提权与精细化权限配置#

在现代 Linux 服务器运维中,**“绝对禁止直接使用 root 登录”**是第一安全铁律。所有的高危操作都应该由普通用户通过 sudo 命令临时提权来完成。这样不仅能收敛权限,还能在系统日志(/var/log/secure 或 /var/log/auth.log)中留下清晰的操作审计记录。

3.1 为什么必须用 visudo?#

配置 sudo 权限就是修改 /etc/sudoers 文件。

IMPORTANT生死攸关的规范

绝对禁止使用 vim /etc/sudoers 直接修改!必须使用 visudo 命令。 visudo 会在保存退出时自动进行语法校验。如果你用 vim 写错了一个符号,会导致全公司所有人都无法使用 sudo,连 root 都切不进去,系统直接“变砖”! ::

3.2 配置文件核心语法拆解#

用 visudo 打开配置后,你会看到类似这样的配置格式:

root ALL=(ALL:ALL) ALL

这五个部分的含义决定了权限的分配逻辑:

  1. 谁来执行:root(可以是用户名,也可以是 %组名)
  2. 在哪里执行:第一个 ALL(表示可以在任何主机/网络上执行)
  3. 以谁的身份:括号里的第一个 ALL(表示可以切换成系统里的任何用户,通常是 root)
  4. 以什么组的身份:括号里的第二个 ALL(可省略,表示任何用户组)
  5. 能执行什么命令:最后一个 ALL(表示允许执行所有命令,必须写命令的绝对路径)

3.3 企业级场景配置实战#

在实际企业中,我们不会给每个人都分配 ALL 权限,而是会根据岗位职责进行“精细化切割”。

场景 1:给高级运维分配所有权限(免密)#

默认情况下,每次敲 sudo 都要输一次自己的登录密码,非常繁琐。对于核心运维,可以配置免密执行。

/etc/sudoers
# 允许 wheel 组的所有成员执行任何命令,并且不需要输入密码
%wheel ALL=(ALL) NOPASSWD: ALL

场景 2:给开发人员开放特定服务的重启权限#

开发人员经常需要重启自己的项目服务,但绝对不能给他们删库的权限。

/etc/sudoers
# 允许 devuser 用户免密执行重启 docker 服务和操作 docker 容器的命令
# 注意:命令必须写绝对路径!
devuser ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart docker, /usr/bin/docker *

场景 3:黑名单机制(防范内鬼提权)#

给某个外包团队分配了几乎所有权限,但唯独要防范他们修改 root 密码或切换到 root。

/etc/sudoers
# 允许 opsadmin 执行所有命令,但禁止切换到root、禁止改root密码、禁止改sudoers文件
opsadmin ALL=(ALL) ALL, !/usr/bin/su, !/usr/bin/passwd root, !/usr/sbin/visudo

3.4 进阶技巧:使用命令别名 (Cmnd_Alias) 简化配置#

当系统里有几十个开发人员、十几个服务需要管理时,一行行写绝对路径会让人崩溃。/etc/sudoers 支持使用别名来将命令和人员打包。

/etc/sudoers
# 1. 定义用户别名(把张三、李四打包成 WEB_ADMINS)
User_Alias WEB_ADMINS = zhangsan, lisi
# 2. 定义命令别名(把所有和 Nginx 相关的命令打包成 NGINX_CMDS)
Cmnd_Alias NGINX_CMDS = /usr/bin/systemctl start nginx, /usr/bin/systemctl stop nginx, /usr/bin/systemctl reload nginx
# 3. 将别名绑定:允许 WEB_ADMINS 组的人免密执行 NGINX_CMDS 里的命令
WEB_ADMINS ALL=(ALL) NOPASSWD: NGINX_CMDS
TIP配置分离的最佳实践

在现代 Linux 中,我们通常不直接修改 /etc/sudoers 主文件。而是会在 /etc/sudoers.d/ 目录下,为每个项目或团队新建一个独立的配置文件(例如 visudo -f /etc/sudoers.d/dev_team)。这样不仅方便管理,也避免了多人同时修改主文件引发冲突。 ::

四、Linux文件权限体系及修改#

4.1 符号与数字八进制转换阵列#

Linux文件将权限拆分为所有者 (u)、所属组 (g) 和其他用户 (o) 三维控制体。

权限类型标识符号八进制数字对普通文件的作用对目录的作用核心效果
读 (Read)r4可以 cat, less 阅览内容可以 ls 列出目录结构名单
写 (Write)w2可以 vim 修补和覆盖内容允许在目录内部 touch, rm 文件
执行 (Execute)x1将脚本作为二进制进程投递运行通行证:可以 cd 进入该目录底层

4.2 赋权操作:chmod 与 chown#

在 Linux 中,权限的修改分为两部分:改权限(谁能干嘛)用 chmod,改归属(这是谁的)用 chown。

1. chmod:修改权限(Change Mode)#

chmod 支持两种写法:数字法(如 755)和字母法(如 u+x)。在自动化运维脚本中,数字法最为高效和普及。

字母法参数速查表:

对象控制符含义授权操作符含义权限符含义
u所有者 (user)+增加权限r读
g所属组 (group)-撤销权限w写
o其他人 (other)=精确覆盖权限x执行
a所有人 (all)
Terminal
# 【经典组合】所有者具有完全读写,组及其他仅可读
chmod 644 config.yml
# 【追加执行权限】(常用于自己刚写完的脚本)
chmod +x script.sh # 等价于 chmod a+x (给所有人加执行权限)
chmod u+x script.sh # 只给所有者自己加执行权限
# 【基线规范】递归分离化授权:网站目录赋755,文件降权至644(防止黑客上传的图片被当成木马执行)
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;

2. chown:修改所有者和所属组(Change Owner)#

当使用 root 账号解压、拉取了属于普通用户的代码,或者创建了日志目录时,务必使用 chown 修正归属。否则普通用户的服务(如 Nginx、MySQL)将因没有权限读取文件而启动失败,这是排查权限报错(Permission denied)时最常干的事。

chown 参数与语法速查表:

语法格式作用说明常见场景
chown user 文件仅修改文件所有者为 user改变单个文件的控制权
chown user:group 文件同时修改所有者为 user,所属组为 group最常用格式,冒号 : 或点 . 是分隔符
chown :group 文件仅修改所属组(相当于 chgrp group 文件)开放某个文件给特定协作组读写
chown -R ...递归修改整个目录及其内部所有子文件/目录给网站根目录或数据盘批量易主
Terminal
# 1. 仅修改文件所有者为 testuser
chown testuser deployment.sh
# 2. 仅修改文件所属组为 developers(前面留空只写冒号和组名)
chown :developers deployment.sh
# 3. 同时修改所有者为 testuser,且所属组变更为 developers
chown testuser:developers deployment.sh
# 4. 【核心参数 -R】深度易主:递归转移整个层级目录属权(运维最高频操作)
# 场景:你用 root 拉取了最新的前端代码放到 /var/www/html,
# 必须把整个文件夹移交给 nginx 账号,否则网页会报 403 Forbidden
chown -R nginx:nginx /var/www/html/

4.3 高级进阶:特殊权限(SUID/SGID/SBIT)#

除了普通的 rwx,Linux 还有三个高级权限位,它们能打破常规的安全壁垒:

  1. SUID (4):只能作用于可执行的二进制程序。普通用户在执行这个程序时,会临时获得程序所有者的权限。最经典的例子是 /usr/bin/passwd,普通用户能靠它修改 /etc/shadow 就是因为 SUID。
  2. SGID (2):作用于目录时,任何人在该目录下创建的新文件,所属组都会自动继承该目录的所属组。(常用于团队共享协作目录)。
  3. SBIT 粘滞位 (1):只能作用于目录。在该目录下,用户只能删除自己创建的文件,不能删除别人的文件。最经典的例子是公共临时目录 /tmp(权限是 1777)。
Terminal
# 赋予 SUID 权限(数字法在原有的三位前加 4)
chmod 4755 /usr/local/bin/myapp
# 赋予 SGID 权限
chmod 2775 /shared_data/
# 赋予 SBIT 粘滞位
chmod 1777 /company_tmp/

4.4 权限防护盾:默认掩码 Umask 控制#

为什么我们 touch 一个新文件,它的默认权限是 644,而 mkdir 一个新目录,默认权限是 755?这就是被 umask 拦截处理后的结果。

  • 新建文件的默认最高基底权限为 666(系统禁止文件一创建就有执行权限)。
  • 新建目录的默认最高基底权限为 777。
  • 最终生成的权限值 = 基底基数 - umask。

系统默认的 umask 是 022,所以:

  • 文件:666 - 022 = 644
  • 目录:777 - 022 = 755
/etc/profile
# 在全局环境拦截高危文件建立(针对协同配合进行微调)
if [ "$UID" -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
umask 022
umask 002 # 改为002,协同组创建的文件权限将自动变为664,目录变为775,方便同组人互相修改
fi

五、最佳实践基线#

安全环境非一朝一夕之功。参考著名的自动化加固库 ::github{repo=“devsecops/ansible-os-hardening”},我们梳理了以下强制准则:

  1. 禁止直接使用root通过SSH登录:配置 PermitRootLogin no,所有提权动作必须依赖具备审计记录的 sudo 流水线。
  2. 遵循特权剥离原则 (Principle of Least Privilege):严苛梳理 sudoers 条目,只分配恰好足够运维业务存活的执行命令名单。
  3. 用户组化管理:拒绝“一号一授权”,采用“组绑定角色,账号分配到组”的标准化RBAC模型。
  4. 死角审计跟踪:定期轮询分析授权日志 :spoiler[/var/log/secure] 或 :spoiler[/var/log/auth.log],提取异常提取命令序列。
  5. 慎用特殊位权限:SUID 是黑客提权的最爱。定期通过 find / -perm -4000 -type f 猎杀潜伏的非法 SUID 文件,拔除系统的“定时炸弹”。
Linux基础(5):Linux用户与权限管理体系详解
https://www.6ixblog.site/posts/linux-basic-5-2/
作者
Licwic
发布于
2025-01-06
许可协议
CC BY-NC-SA 4.0