一、权限是什么?

Linux 是多用户多任务系统,文件权限决定了“谁能对文件做什么”。对运维和日常使用来说,理解权限是避免“Permission denied”的第一步,也是配置共享目录、保护敏感文件的基础。

权限模型分为三层:传统 UGO 权限(属主、属组、其他人)→ ACL 扩展权限(细粒度控制)→ 特殊权限位(如 setgid)。三层配合使用,基本能覆盖所有权限管理场景。

二、基础权限(UGO 模型)

1. 查看权限:ls -l

执行 ls -l 会看到类似这样的输出:

-rwxrw-r-- 1 alice devops 1024 Apr 16 10:00 script.sh

最前面的 10 个字符是关键,分成四组理解:

位置示例含义
第 1 位-文件类型:-普通文件、d目录、l符号链接、b块设备、c字符设备
第 2-4 位rwx属主权限(user)
第 5-7 位rw-属组权限(group)
第 8-10 位r--其他人权限(others)

每个权限位由 r(读)、w(写)、x(执行)组成,缺失用 - 表示。

对文件和目录的不同含义

权限对文件对目录
r读取文件内容列出目录内容(需同时有 x
w修改文件内容在目录内创建/删除/重命名文件(需同时有 x
x执行文件(脚本/程序)进入目录、访问目录内文件的元数据

常见误区:给目录只加 r 不加 x,你依然无法 ls 进去,因为 x 是“通行证”。目录的 w 需要 x 配合才能生效。

2. 权限的数字表示(八进制)

rwx 分别对应数值 4、2、1,组合相加得到权限码:

权限数值
rwx7
rw-6
r-x5
r--4
-wx3
-w-2
--x1
---0

一个完整的权限可以用三个数字表示:属主权限属组权限其他人权限。例如 755 表示 rwxr-xr-x

3. 修改权限:chmod

# 符号方式
chmod u+x file.sh      # 属主加执行
chmod g-w file.sh      # 属组去掉写
chmod o=r file.sh      # 其他人设为只读
chmod a+x script.sh    # 所有人加执行

# 数字方式
chmod 755 script.sh    # rwxr-xr-x
chmod 644 config.conf  # rw-r--r--

4. 修改属主/属组:chownchgrp

# 修改属主
chown alice file.txt

# 同时修改属主和属组
chown alice:devops file.txt

# 只修改属组
chgrp devops file.txt

普通用户只能将自己名下文件的属组改为自己所在的组,且必须是该组的成员。修改属主需要 root 权限。

5. 权限判断逻辑

当用户访问一个文件时,系统按以下顺序决定权限:

  1. 如果用户是文件的属主 → 应用属主权限。
  2. 否则,如果用户属于文件的属组(或文件所在组的成员) → 应用属组权限。
  3. 否则 → 应用其他人权限。

注意:只命中第一个符合条件的规则,不会叠加。如果用户既是属主又属于属组,只使用属主权限。

三、ACL(访问控制列表)—— 突破 UGO 限制

传统 UGO 权限只能指定一个属主、一个属组、一组其他人。现实场景中常常需要:

  • 给特定用户(如 tempuser)单独的读写权限,但不希望他成为属主。
  • 给多个不同组的成员不同权限。
  • 让新建文件自动继承父目录的 ACL 规则。

ACL 就是用来解决这些问题的。

1. 查看 ACL

getfacl file.txt

输出示例:

# file: file.txt
# owner: alice
# group: devops
user::rw-
user:bob:r--
group::r--
mask::r--
other::---

2. 设置 ACL

# 给特定用户添加权限
setfacl -m u:bob:rwx file.txt

# 给特定组添加权限
setfacl -m g:project:r-x dir/

# 移除某条 ACL
setfacl -x u:bob file.txt

# 递归设置目录 ACL(新文件继承?需要配合默认 ACL)
setfacl -R -m u:bob:r-x dir/

3. 默认 ACL(继承)

对目录设置默认 ACL 后,目录内新建的文件/子目录会自动继承规则。

setfacl -m d:u:bob:r-x dir/   # 设置默认 ACL
setfacl -k dir/                # 移除默认 ACL

4. mask 概念(重要!)

ACL 引入了一个 mask 值,它表示“当前 ACL 条目的最大有效权限”。任何用户或组的实际权限不能超过 mask 的权限位。

查看 getfacl 输出中的 mask::r-x 这一行。如果 mask 是 r-x,即使某条 ACL 条目写着 rwx,实际生效的也是 r-x

常见问题:用 chmod 修改文件权限时,可能会意外修改 mask。建议使用 setfacl -m mask:rwx file 来单独调整 mask。

个人习惯:每次设置 ACL 后,用 getfacl 确认 mask 是否符合预期。如果发现权限不生效,优先检查 mask。

四、setgid —— 让目录内的新文件自动继承属组

setgid(Set Group ID)是一个特殊权限位,主要用于目录:当目录设置了 setgid,该目录下新建的文件/子目录会自动继承目录的属组,而不是继承创建者的默认属组。

这对于团队共享目录非常有用。

1. 设置 setgid

# 数字方式:在权限前面加 2
chmod 2775 shared_dir/

# 符号方式
chmod g+s shared_dir/

2. 查看 setgid

ls -l 中,属组的 x 位会变成 s(如果原来有执行权限)或 S(如果原来没有执行权限)。

drwxrwsr-x 2 alice devops 4096 Apr 16 10:00 shared_dir/
#      ↑ 这个 s 表示 setgid 已设置

3. setgid 的效果

# 假设 shared_dir 属组为 devops,设置了 setgid
$ ls -ld shared_dir/
drwxrwsr-x 2 alice devops 4096 Apr 16 10:00 shared_dir/

# 用户 bob(属于 devops 组)在目录内新建文件
$ touch shared_dir/newfile.txt
$ ls -l shared_dir/newfile.txt
-rw-r--r-- 1 bob devops 0 Apr 16 10:01 newfile.txt
#               ↑ 属组自动变成了 devops,而不是 bob 的默认组

这样,同组成员都能互相访问彼此新建的文件(前提是权限允许)。

注意:setgid 只影响新建的文件,已有文件的属组不会改变。

五、umask —— 新建文件/目录时的默认权限掩码

umask 决定了新创建文件或目录的默认权限。它不是一个权限设置,而是一个“减去”的值。

1. 规则

  • 文件的默认基准权限是 666rw-rw-rw-)。
  • 目录的默认基准权限是 777rwxrwxrwx)。
  • 最终权限 = 基准权限 – umask 值(按位减去)。

常见 umask 值及效果

umask新文件权限新目录权限
022644(rw-r--r--755(rwxr-xr-x
002664(rw-rw-r--775(rwxrwxr-x
077600(rw-------700(rwx------

2. 查看和设置 umask

# 查看当前 umask(数字形式)
umask
# 输出 022

# 设置 umask(临时,仅当前 shell)
umask 002

# 永久设置:写入 ~/.bashrc 或 /etc/profile
echo "umask 002" >> ~/.bashrc

个人习惯:在多用户协作的服务器上,我把 umask 设为 002,这样同组成员创建的文件默认可被组内其他人修改,减少权限问题。

六、综合案例:配置一个组内共享工作目录

需求:有一个项目组 proj,成员包括 alicebobcarol。需要创建一个共享目录 /data/project,要求:

  1. 只有 proj 组的成员可以进入和操作该目录。
  2. 目录内新建的文件/子目录自动继承 proj 组,组成员可以互相编辑。
  3. 项目经理 alice 拥有删除任意文件的权限,普通成员不能删除他人创建的文件(除非文件权限允许)。
  4. 临时成员 tempuser 只有只读访问权限。

步骤 1:创建组和用户

# 创建组
groupadd proj

# 添加用户并加入组
useradd -G proj alice
useradd -G proj bob
useradd -G proj carol
useradd tempuser   # 临时用户,不属于 proj 组

# 设置密码(略)

步骤 2:创建共享目录并设置基础权限

mkdir -p /data/project
chown root:proj /data/project   # 属组设为 proj
chmod 2770 /data/project        # 权限 2770:rwxrwx--- + setgid
  • 2770:属主 root 有全部权限,属组 proj 有全部权限,其他人无权限。
  • 2(setgid):确保目录内新建文件的属组自动为 proj

检查:

ls -ld /data/project
# drwxrws--- 2 root proj 4096 Apr 16 10:00 /data/project

步骤 3:使用 ACL 添加临时用户的只读权限

setfacl -m u:tempuser:r-x /data/project
# 注意:对目录需要 r 和 x 才能进入和列出内容

步骤 4:给项目经理额外的删除权限(可选,因为已经是属组成员)

实际上 alice 作为 proj 组成员,已经有 rwx 权限,可以删除任意文件。但如果希望限制普通成员不能删除他人文件,可以调整 umask 和 ACL 的 mask,或者使用更细粒度的 ACL 对 alice 赋予特殊权限(但这里默认已经满足)。

更严格的场景:普通成员只能删除自己创建的文件。这需要依赖粘滞位(sticky bit),例如 /tmp 目录的 t 权限。可以在共享目录设置粘滞位:

chmod +t /data/project   # 添加粘滞位,使得只有文件属主、目录属主、root 能删除文件

但粘滞位与 setgid 同时使用需要注意:chmod 3770 /data/project(3 = setgid + sticky)。

不过本案例不强制要求粘滞位,按需求灵活选择。

步骤 5:配置 umask 确保组成员默认可写

要求每个成员在自己的 shell 环境(或系统全局)设置 umask 为 002

# 在 /etc/profile 或 /etc/bash.bashrc 中添加
if [ $UID -gt 199 ] && [ "`id -gn`" = "`id -un`" ]; then
    umask 002
else
    umask 022
fi

这样新文件权限为 664rw-rw-r--),新目录权限为 775rwxrwxr-x),组成员可互相修改。

步骤 6:验证

bob 身份登录,在 /data/project 中创建文件:

su - bob
cd /data/project
echo "hello" > bob.txt
ls -l bob.txt
# -rw-rw-r-- 1 bob proj 6 Apr 16 10:05 bob.txt
#          ↑ 属组为 proj,组成员可写

alice 身份登录,尝试修改 bob.txt

su - alice
echo "world" >> /data/project/bob.txt   # 成功

tempuser 身份登录,尝试写文件:

su - tempuser
touch /data/project/temp.txt
# touch: cannot touch 'temp.txt': Permission denied

但可以读:

cat /data/project/bob.txt   # 成功

配置完成。

七、速查表

操作命令
查看权限ls -l
修改权限(数字)chmod 755 file
修改权限(符号)chmod u+x,g-w,o=r file
修改属主chown alice file
修改属组chgrp devops file
查看 ACLgetfacl file
设置 ACL(用户)setfacl -m u:bob:rwx file
设置 ACL(组)setfacl -m g:proj:rx file
设置默认 ACL(继承)setfacl -m d:u:bob:rx dir/
移除 ACLsetfacl -x u:bob file
设置 setgid(数字)chmod 2775 dir
设置 setgid(符号)chmod g+s dir
设置粘滞位chmod +t dir
查看 umaskumask
设置 umaskumask 002

八、个人经验总结

  1. 优先使用 UGO + setgid 解决大部分共享目录需求,ACL 作为补充(如给特定用户只读)。
  2. 不要滥用 ACL,它会让 ls -l 无法完整显示权限,排查问题记得用 getfacl
  3. setgid 是共享目录的好帮手,配合 umask 002 可以省去大量 chgrp 操作。
  4. mask 是个隐藏坑:如果 ACL 不生效,先检查 mask。
  5. 新文件权限异常:检查 umask 是否符合预期,尤其是不同用户的默认 umask 可能不同。

作者

884705373@qq.com

相关文章

QLoRA微调原理详解:与LoRA的性能与内存对比

引言:为什么大模型微调需要QLoRA? 在深...

读出全部

关于Norm的解析

可以说,如果没有残差连接和 Layer No...

读出全部

从 SGD 到 AdamW 的优化器

写在前面 在上一篇文章中,我们讨论了如何用数...

读出全部