☰
【Linux】 权限篇(三):深入理解 umask 位运算与粘滞位的设计思想
2026/10/23 4:57:38 网站建设 项目流程

一、引言:Linux 为什么要控制默认权限?

在前两篇中,我们学习了 Linux 的文件属性、基本权限,以及如何使用chmod、chown和chgrp修改权限。

但还有两个问题值得继续思考:

  1. 使用touch创建一个文件时,我们没有指定权限,为什么文件仍然会自动获得一组权限?
  2. 在一个允许所有用户写入的公共目录中,为什么用户可以创建自己的文件,却不应该随意删除其他用户的文件?

第一个问题涉及umask:新建文件和目录的默认权限如何产生。

第二个问题涉及Sticky Bit(粘滞位):如何在允许共享的同时限制删除行为。

这两个知识点看似独立,实际上体现了 Linux 权限设计的两个目标:

  • 创建资源时,默认权限不能过度开放。
  • 共享资源时,不能只考虑协作便利,还要考虑资源保护。

二、umask:新建文件的权限是怎么来的?

2.1 先观察一个现象

在 Ubuntu 终端中执行:

umask

假设输出:

0002

这表示当前 Shell 的文件创建权限掩码为0002。

接下来创建一个文件和一个目录:

touchtest.txtmkdirtest_dirls-ltest.txtls-ldtest_dir

在没有其他权限机制干预的常见情况下,可以观察到:

-rw-rw-r-- test.txt drwxrwxr-x test_dir

对应的权限数字分别是:

test.txt -> 664 test_dir -> 775

问题来了:我们没有执行chmod,为什么它们会得到这些权限?

原因是,创建文件和目录时,程序会向操作系统提出创建请求,并提供一个期望的初始权限模式。内核再结合当前进程的umask等权限规则,确定新对象的权限。

因此,umask不是事后修改权限的命令,而是影响新建文件和目录默认权限的掩码。

2.2 先回顾 rwx 的数字表示

Linux 使用三位二进制位表示一组基本权限:

权限二进制八进制数值
r1004
w0102
x0011

每个文件通常分别设置拥有者、所属组和其他用户的权限。

例如:

-rw-rw-r--

拆分为:

rw- rw- r-- 用户 用户组 其他用户

对应:

664

其中:

  • 用户拥有读、写权限:4 + 2 = 6
  • 用户组拥有读、写权限:4 + 2 = 6
  • 其他用户只有读权限:4

理解了这个基础,才能继续理解umask为什么能够屏蔽权限。

2.3 文件和目录的起始权限为什么不同?

在常见的 Linux 文件创建机制中,用于计算默认权限的基础模式通常是:

对象类型基础模式含义
普通文件666rw-rw-rw-
目录777rwxrwxrwx

这里的基础模式不是说最终创建出来的文件一定具有这些权限,而是计算时使用的基础值。

为什么普通文件的基础模式不是777?

因为普通文件默认不应自动获得执行权限。一个刚刚创建的文本文件通常只是数据,不应该仅仅因为它被创建出来,就默认成为可执行文件。

目录则不同:目录的x权限与进入、搜索目录有关,因此目录的基础模式通常包含执行权限。

注意:程序可以请求不同的创建模式,文件系统也可能受到 ACL 等机制影响。因此,这里的666和777是理解常见默认权限计算的基础模式,不代表所有创建操作都必然采用它们。


三、umask 的核心:不是减法,而是位运算

3.1 umask 究竟屏蔽了什么?

可以先记住一句话:

umask中对应权限位为1的位置,表示该权限位不应出现在最终权限中。

例如:

umask = 0002

最后一位的八进制数字2,对应二进制:

010

它代表屏蔽其他用户权限组中的写权限位。

于是,新建文件时,基础模式中的其他用户写权限就会被屏蔽。

这也解释了为什么umask 0002通常会让新建文件的权限从666变为664。

3.2 为什么公式是 mode & ~umask?

常见的权限计算表达式为:

final_mode=requested_mode&~umask;

这里涉及两个位运算符:

  • ~:按位取反。
  • &:按位与。

先看按位与的规则:

ABA & B
000
010
100
111

按位与的核心特点是:只有两边都为1,结果才是1。

因此,如果我们希望某个权限位被保留,就需要让基础模式和掩码取反后的对应位都为1。

如果掩码中的某个权限位是1,取反之后就会变成0。基础模式与这个0进行按位与,结果只能是0,对应权限便被屏蔽了。

这就是umask的底层逻辑。

3.3 手动推导:umask 0002

先看新建目录。

基础模式:

777 = 111 111 111

掩码:

002 = 000 000 010

取反后,只保留我们需要讨论的低九个权限位:

~002 = 111 111 101

执行按位与:

111 111 111 777:目录基础模式 & 111 111 101 ~002:屏蔽写权限位 ------------- 111 111 101 775:最终权限

因此:

777 & ~002 = 775

再看普通文件。

110 110 110 666:文件基础模式 & 111 111 101 ~002 ------------- 110 110 100 664:最终权限

因此:

666 & ~002 = 664

这里的二进制演算只展示权限所使用的九个基本权限位。实际计算机中的按位取反还会涉及更高位,所以不能把无限位宽的~002直接理解为一个只有九位的数;我们展示的是权限位范围内的结果。

3.4 为什么不能直接做减法?

看到:

666 - 002 = 664 777 - 002 = 775

你可能会觉得,直接相减不就行了吗?

但这只是部分例子中碰巧得到相同结果,不能作为通用算法。

原因在于:umask表示的是需要屏蔽哪些权限位,而不是需要从权限数字中减去多少。

例如:

基础模式:666 umask: 022

正确结果:

666 & ~022 = 644

如果用普通减法:

666 - 022 = 644

这次结果相同。

但再看:

基础模式:666 umask: 003

按照位屏蔽规则:

  • 003表示屏蔽其他用户组的写权限和执行权限对应的位。
  • 普通文件基础模式666本身没有执行权限,因此屏蔽执行权限不会产生额外变化。
  • 屏蔽其他用户的写权限后,最终权限为664。

而直接做八进制减法:

666 - 003 = 663

得到的结果反而让其他用户失去了读权限,并没有正确表达“屏蔽写和执行权限”的含义。

结论:权限掩码操作的是二进制权限位,因此必须按照位运算规则理解,不能将其等同于数字减法。


四、在 Ubuntu 中验证 umask

4.1 查看当前掩码

umask

如果想看到符号形式,可以执行:

umask-S

输出形式可能类似:

u=rwx,g=rwx,o=rx

具体输出以当前 Shell 环境为准。

4.2 临时修改掩码

可以在当前终端中执行:

umask0002

然后创建测试对象:

touchumask_filemkdirumask_dirls-lumask_filels-ldumask_dir

在常见默认创建模式下,预期分别为:

-rw-rw-r-- umask_file drwxrwxr-x umask_dir

对应:

664 775

如果你想验证不同掩码的效果,可以尝试:

umask0022touchfile_0022mkdirdir_0022ls-lfile_0022ls-lddir_0022

常见结果:

file_0022 -> 644 dir_0022 -> 755

再尝试:

umask0077touchprivate_filemkdirprivate_dirls-lprivate_filels-ldprivate_dir

常见结果:

private_file -> 600 private_dir -> 700

这时新建文件只有拥有者能够读写,新建目录只有拥有者具有完整的基本权限。

4.3 umask 修改后会永久生效吗?

通常不会。

直接执行:

umask0077

会修改当前 Shell 的掩码,当前 Shell 创建的子进程通常也会继承相应的掩码状态。退出该 Shell 后,重新登录时的掩码可能由启动配置重新设置。

如果确实需要长期修改,可以根据自己的 Shell 环境,在对应的用户启动配置文件中设置。但在学习阶段,建议先在当前终端实验,不要随意修改全局配置。

特别注意:不要在不理解影响范围的情况下,把严格或过于宽松的umask设置写进系统级配置。


五、从默认权限转向共享目录:出现了什么矛盾?

理解umask后,我们再看第二个问题。

假设一台 Linux 服务器上有多个普通用户,他们都需要在一个公共目录中创建临时文件。

如果公共目录不允许其他用户写入,那么协作就会受限。

但如果为了方便协作,直接允许所有用户读、写、进入这个目录,又会带来新的问题:

用户可能删除自己并不拥有的文件。

这里有一个很容易误解的知识点:

删除目录中的文件,通常主要检查的是父目录的权限,而不是被删除文件本身的写权限。

5.1 为什么删除文件看的是目录权限?

例如,目录结构如下:

/shared/ └── alice.txt

假设:

  • /shared允许某个用户写入并搜索。
  • alice.txt属于 Alice。
  • 该用户不是 Alice,也不是 root。

即使alice.txt本身没有授予该用户写权限,如果该用户对父目录具有足够的权限,且没有其他限制,仍然可能删除这个目录项。

为什么?

从文件系统的角度看,删除文件并不等同于打开文件并修改内容。删除操作需要修改的是父目录中的目录项,也就是让目录不再记录这个文件名与对应对象之间的关联。

因此:

  • 修改文件内容,主要检查文件自身的写权限。
  • 删除或重命名目录中的条目,主要检查父目录的写权限和搜索权限。

这就是为什么“文件不可写”并不一定意味着“文件不可删除”。

5.2 用流程图理解删除权限

否

是

否

是

是

否

用户尝试删除文件

检查父目录权限

是否具有必要的写权限和搜索权限

通常拒绝操作

是否存在粘滞位等额外限制

通常允许删除目录项

继续检查删除者身份

是否为允许删除的用户

允许删除

拒绝删除

这个流程是帮助理解的简化模型。实际操作还可能受到 ACL、只读挂载、文件系统属性等因素影响。

现在,问题就明确了:

我们希望用户可以在公共目录中创建自己的文件,但不能随意删除别人的文件。

这正是粘滞位要解决的核心问题。


六、Sticky Bit:让公共目录既能共享,又能保护文件

6.1 什么是粘滞位?

Sticky Bit,中文通常称为“粘滞位”,是一种特殊权限位。

在现代 Linux 中,它最常见的用途是保护设置了该权限的共享目录。

当目录设置了粘滞位后,即使用户对目录拥有写权限,也不能因此随意删除或重命名其他用户的文件。

在典型的目录场景中,允许删除目录项的身份包括:

  1. 文件的拥有者。
  2. 目录的拥有者。
  3. 超级用户 root。

当然,操作仍然需要满足其他适用的权限与系统规则。

6.2 粘滞位在权限字符串中如何显示?

观察一个常见的权限字符串:

drwxrwxrwt

最后的t就是粘滞位的标志。

普通目录权限的最后一位通常对应其他用户的执行权限;设置粘滞位后:

  • 如果其他用户执行权限也存在,通常显示为小写t。
  • 如果其他用户执行权限不存在,则通常显示为大写T。

例如:

drwxrwxrwt drwxrwxrwT

这两个字符串都体现了粘滞位,但对应的执行权限情况不同。

6.3 为什么/tmp通常有粘滞位?

Linux 系统中的/tmp通常用于存放临时文件。

多个程序、多个用户可能同时使用这个目录,因此它需要允许不同用户创建临时文件。

可以查看:

ls-ld/tmp

常见输出类似:

drwxrwxrwt ... /tmp

重点看末尾的t。

/tmp通常具有:

  • 所有者的完整权限。
  • 所属组和其他用户的读、写、执行权限。
  • 粘滞位。

这意味着普通用户可以在其中创建临时文件,但不能仅仅因为目录可写,就随意删除其他用户拥有的文件。

因此,/tmp展示了一种典型的权限设计思路:

允许共享目录本身,同时对目录项的删除和重命名增加身份限制。


七、如何设置粘滞位?

7.1 使用符号方式

假设我们创建一个用于实验的目录:

mkdirsticky_demochmod777sticky_demols-ldsticky_demo

此时,权限通常类似:

drwxrwxrwx ... sticky_demo

设置粘滞位:

chmod+t sticky_demo

再次查看:

ls-ldsticky_demo

预期看到:

drwxrwxrwt ... sticky_demo

最后的t表示粘滞位已设置。

这里使用的是自己创建的实验目录,不需要修改系统目录,也不需要执行危险的全局权限修改。

7.2 使用数字方式

Linux 也支持使用特殊权限位的数字表示。

粘滞位对应的数值为1,写在普通三位权限数字之前。

例如:

chmod1777sticky_demo

其中:

1 777 │ └── 普通权限:rwxrwxrwx └──── 粘滞位

执行后,目录的权限通常会显示为:

drwxrwxrwt

需要注意,特殊权限位与普通的rwx权限位属于不同的概念,不要把1777理解成四组普通读写执行权限。


八、umask 和粘滞位有什么本质区别?

这两个知识点都与 Linux 权限有关,但它们解决的是不同阶段的问题。

对比项umaskSticky Bit
主要作用控制新建对象的默认权限限制共享目录中的删除、重命名行为
主要生效时机创建文件或目录时对设置了粘滞位的目录进行相关操作时
关注对象新建对象的基本权限位目录中的文件条目及相关用户身份
常见使用方式umask 0022chmod +t directory
典型场景避免新建文件默认过度开放保护/tmp一类共享目录中的文件

可以这样理解:

  • umask关注的是:一个对象刚创建出来时,默认应该开放哪些权限?
  • 粘滞位关注的是:一个目录允许多人共同使用时,谁可以删除其中的文件?

一个控制创建阶段的默认权限,一个在共享目录场景中增加删除与重命名的限制。二者互不替代。


九、常见误区总结

误区一:umask 是从默认权限中直接减去一个数字

错误。

umask表示需要屏蔽的权限位。应从位运算角度理解:

最终权限 = 请求的基础权限 & ~umask

误区二:新建文件一定是 666,新建目录一定是 777

不准确。

它们是常见计算场景中的基础模式。最终权限还取决于创建请求、umask以及可能存在的其他权限机制。

误区三:文件没有写权限,就一定不能删除

错误。

删除文件通常主要检查父目录的写权限和搜索权限;设置粘滞位后,还需要检查相关用户身份。

误区四:目录有粘滞位,就不能删除里面的文件

错误。

粘滞位并不是禁止所有删除操作,而是限制哪些用户可以删除或重命名目录中的条目。文件拥有者、目录拥有者和 root 通常仍然可以删除符合条件的文件。

误区五:只要设置了粘滞位,其他权限就不重要了

错误。

粘滞位不会代替目录的基本权限检查。用户仍然需要满足适用的访问条件,粘滞位是在相关权限检查之外增加的一层限制。


十、总结

本篇学习了 Linux 权限管理中的两个重要机制。

第一,umask通过屏蔽权限位影响新建文件和目录的默认权限。理解它的关键不是记住几个数字,而是理解按位取反与按位与的运算逻辑。

第二,Sticky Bit 用于解决共享目录中的权限矛盾。它允许用户在公共目录中协作,同时限制普通用户随意删除或重命名其他用户的文件。

回到最初的两个问题:

  • 为什么新建文件会自动获得一组权限?因为创建请求的基础权限会受到umask等规则的影响。
  • 为什么公共目录可以允许多人写入,却又保护其他人的文件?因为粘滞位能够在共享目录中增加身份方面的限制。

Linux 权限管理并不是简单地给文件设置几个rwx标志,而是围绕资源访问、默认安全性和多用户协作建立起来的一套机制。

当我们能够从“为什么需要这条规则”出发,再推导它的行为,就不再只是记住命令,而是在理解操作系统的设计思想。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询