"umask"是什么,它是如何工作的?

我相信umask是控制文件权限的东西,但我并不完全理解它。

终端中运行umask 0644后,我无法读取用命令行文本编辑器nano创建的文件。我注意到该文件的权限设置为0022,而不是默认的0755

umask是如何工作的?我以为只需从0777中去除umask中的每个数字,7 - 6 = 17 - 4 = 3,所以我期望权限是0133,但显然情况并非如此。

  1. umask到底是什么?请像对待一个“Linux新手”一样向我解释。
  2. 如何使用umask进行计算?
  3. umask有哪些使用场景?

app_mode 666 rw- rw- rw- umask 644 --0 -00 -00 file_mode 022 --- -w- -w- - grabantot
https://askubuntu.com/q/186747/459652 - user459652
1你假设中的主要问题是:不要总是从777中“减去”,而是对目录从777中减去,对文件从666中减去。就是这样。 - phil294
7个回答

umask作为一组权限,应用程序无法在文件上设置。它是进程的文件模式创建掩码,不能为目录本身设置。大多数应用程序不会创建具有执行权限的文件,因此它们的默认值为666,然后由umask进行修改。
如果您将umask设置为删除所有者的读/写位和其他人的读位,那么应用程序中的默认值(例如777)将导致文件权限为133。这意味着您(和其他人)可以执行该文件,而其他人则可以对其进行写入。
如果您希望使文件除了所有者之外的任何人都无法读取/写入/执行,您应该使用类似于077的umask来关闭组和其他人的权限。
相比之下,umask为000将使新创建的目录对每个人都可读、可写和可进入(权限将为777)。这样的umask非常不安全,您绝对不应该将umask设置为000。
Ubuntu的默认umask是022,这意味着新创建的文件可以被所有人读取,但只有所有者可以进行写入操作。
user@computer:~$ touch new-file-name
user@computer:~$ ls -dl new-file-name
-rw-r--r-- 1 user user 0 Apr  1 19:15 new-file-name

从Ubuntu Oneiric(11.10)开始,默认的umask被放宽为002,这样扩展了对所有者组的写入权限。
user@computer:~$ touch new-file-name
user@computer:~$ ls -dl new-file-name
-rw-rw-r-- 1 user user 0 Apr  1 19:15 new-file-name

查看和修改umask

要查看当前的umask设置,请打开终端并运行以下命令:

umask

要将当前shell的umask设置更改为其他值,比如077,请运行以下命令:
umask 077

为了测试这个设置是否有效,您可以创建一个新文件(现有文件的文件权限不会受到影响),并显示有关该文件的信息,运行以下命令:
user@computer:~$ touch new-file-name
user@computer:~$ ls -dl new-file-name
-rw------- 1 user user 0 Apr  1 19:14 new-file-name
umask设置会被从同一个shell启动的进程继承。例如,通过在终端执行gedit来启动文本编辑器GEdit,并使用gedit保存文件。您会注意到新创建的文件受到与终端中相同的umask设置的影响。
用例:多用户系统
如果您在一个由多个用户共享的系统上,希望其他人无法读取您的主目录中的文件,那么umask非常有用。编辑~/.profile并添加一行新的内容:
umask 007

您需要重新登录以使此umask更改在〜/ .profile中生效。接下来,您需要通过删除全局的读取、写入和执行权限位来更改主目录中文件的现有权限。打开终端并执行以下命令:
chmod -R o-rwx ~

如果你希望将这个umask设置应用到系统上的所有用户,你可以编辑系统范围的配置文件/etc/profile

3那么,umask中的数字代表什么意思呢?为什么777表示组和其他人可以对其进行写操作,而077则表示他们不能呢? - HelloGoodbye
3还有,你说如果umask为000,文件权限将会是777。所以按照默认掩码022,文件权限不应该是755吗?也就是对应-rwxr-xr-x而不是-rw-r--r-- - HelloGoodbye
1/etc/profile现在已经被弃用。 - aneeshep
23不得不承认,这个解释让我更加困惑,而不是帮助我。 - Connel Hooley
2所以简单来说,umask是设置文件权限的相反操作。umask x chmod。我说得对吗? - sofs1
8请注意,在此回答发布后的一个月内,Ubuntu 的默认 umask 已更改为 0002 - Jeff Puckett
9@HelloGoodbye 如果umask是000,那么不会移除任何权限。像touchnano这样的应用程序会使用默认的666创建文件,所以文件权限将保持为666,但是umask为022会移除组和其他用户的写入位,所以666会被减少为644,即-rw-r--r--。考虑到mkdir命令,默认的创建模式是777,但是umask为022会将权限减少为755 - Jeff Puckett
1对于像我这样理解符号术语而不是八进制数的人来说,umask 0077相当于umask u+rwx,go-rwx。在这种情况下,umask显示了你“想要”的权限而不是你“不想要”的权限,所以更容易理解和表达。 - Paddy Landau

其他人已经很好地解释了umasking的概念以及为什么需要它。让我再补充一下,并给你一个数学例子,说明权限是如何实际计算的。

首先,“mask”并不意味着“减法”,在算术意义上没有借位或进位。

其次,应该逐位理解“掩码”,即独立地对每个位列应用逻辑操作。也就是说,权限位序列的第4位仅与掩码的第4位交互。

第三,掩码关闭权限位。如果它们已经关闭,则umask不会更改权限。

例如,假设您必须从文件的系统默认值666和目录的系统默认值777中取消掩码077

您将使用的命令是

umask 077

(以二进制形式显示值,000 111 111

这个解码器的作用是关闭前六个最低有效位(LSB),如果它们为1,如果其中任何一个已经关闭,则不会进行任何更改。

以下是计算最终权限的方法:

file permission   666 = 110 110 110 
unmask value      077 = 000 111 111
will result in    600 = 110 000 000

观察两个110值如何变为000

同样地,

directory permission   777 = 111 111 111 
unmask value           077 = 000 111 111
will result in         700 = 111 000 000

11这应该是答案! - Abdelouahab
@SufiyanGhori 如果 umask 177 (001 111 111),它将关闭前7个最低有效位,如果它们是 1 - Kasun Siyambalapitiya
没错,@KasunSiyambalapitiya。 - Sufiyan Ghori
4所以公式是结果 = 文件权限 & (!umask) - Eric Hodgins
1@EricHodgins :是的,完全正确。 - Amit Naidu
1在这里,我们可以轻松计算文件权限(只需记住对于文件夹使用777而不是666)。 - SantaXL
实际上有4个数字 :) - Roland

除了接受答案中的良好讨论外,还值得补充一些关于umask的内容,特别是在12.04及以后版本中如何管理它。 Umask和pam_umask 默认的umask现在位于/etc/login.defs而不是/etc/profile,正如/etc/profile中的官方说明所述:
# The default umask is now handled by pam_umask.
# See pam_umask(8) and /etc/login.defs.

Pam_umask的简要解释如下,应该注意的是用户放置自定义umask设置的默认文件仍然是~/.profile

Pam_umask是Ubuntu操作中至关重要的PAM模块之一(运行apropos '^pam_'以查找其他模块的manpages)。在pam_umaskmanpage中指出:

pam_umask是一个PAM模块,用于设置当前环境的文件模式创建掩码。umask影响分配给新创建文件的默认权限。

关于默认umask的说明

$HOME中,可以使用mkdir创建新文件夹,其默认权限为775,并且可以使用touch创建新文件,其默认权限为664,即使默认的umask是022也不例外。这一点起初似乎有些矛盾,值得解释一下。
虽然在Ubuntu上,默认的umask是022,但这并不是全部情况,因为在/etc/login.defs中存在一个设置,如果条件满足,非root用户的umask可以设为002(请参见下面的摘录)。在普通的安装中,/etc/login.defs包含了以下设置:USERGROUPS_ENAB yes。这就是为什么会出现下面的情况:

对于非root用户,允许将umask组位设置为与所有者位相同 (例如:022 -> 002,077 -> 007),前提是uid与gid相同,而且用户名与主要组名相同。

因此,当在像我的单用户系统中使用mkdir创建新文件夹时,您会通过stat命令看到以下情况(uid和gid相同):
Access: (0775/drwxrwxr-x)  Uid: ( 1000/username)   Gid: ( 1000/username)

更多信息,请参阅man pam_umaskUbuntu manpages online

看起来你的第二部分缺少了一些东西?(USERGROUP_ENABLE?)+1 以获取更新的信息。 - Lekensteyn
2@Lekensteyn 奇怪的是,在检查后,/etc/login.defs 中的设置确实是 USERGROUPS_ENAB yes。该文件的语法稍微有些不寻常。 - user76204
我刚刚检查了文件和源代码,你是对的,这个(还有其他一些)设置的命名确实让人困惑,以"_ENAB"结尾。 - Lekensteyn

这个内容虽然有点老,但是还是值得一提的。为了计算umask,与文件系统权限不同,八进制的umask是通过对参数的按位取反再进行按位与运算来计算的。八进制的表示如下:
Octal value : Permission
0 : read, write and execute
1 : read and write
2 : read and execute
3 : read only
4 : write and execute
5 : write only
6 : execute only
7 : no permissions

然后,您可以计算以设置适当的权限umask,如下所示:
$ umask 077
$ mkdir dir1
$ touch file
$ ls -ld dir1 file

drwx------ 2 amrx amrx 4096 2011-03-04 02:05 dir1
-rw------- 1 amrx amrx    0 2011-03-04 02:05 file

计算文件的最终权限

您可以通过从基本权限中减去掩码来确定文件的最终权限,具体如下:

666 – 022 = 644

文件基本权限:666 umask值:022 减去新文件的权限(666-022):644(rw-r--r--)
计算目录的最终权限
您可以简单地从基本权限中减去umask值来确定目录的最终权限,如下所示:
777 – 022 = 755

目录基本权限:777 umask值:022 减去以获取新目录的权限(777-022):755(rwxr-xr-x)

3我不认为最终权限是这样计算的,如果掩码值是077,那么在这种情况下你如何减去666-077呢? - Sufiyan Ghori
7@SufiyanGhori Baron的解释对于文件权限并不完整。在你的情况和任何未来的计算中,为了方便记忆,你应该记住以这种方式进行减法运算:6-0 6-7 6-7 如果这三个结果中有任何一个是-1,则将其视为0。因此我们得到最终结果600。 - Huy.PhamNhu
1@Huy.PhamNhu 这也不正确。使用基本权限666和umask 033,你肯定不会得到633。 - maaartinus
9不不不。你不能使用减法来计算umask(它只适用于某些值,而不是所有值)。你必须将umask视为“禁用位”。请参考Sufiyan和Wisbucky的其他答案。 - wisbucky

基本概念:
如果你和大多数人一样,不明白“通过按位非操作的一元补码与参数进行按位与运算来计算八进制掩码是什么意思”,那么这里有我的简单解释:
首先,想想“掩码”是什么。掩码可以阻止某些东西。想想胶带。在这种情况下,umask就像是胶带,用于在创建新文件或目录时阻止/禁用权限。
创建新目录时的默认权限是八进制777(111 111 111),而新文件是八进制666(110 110 110)。我们设置umask来阻止/禁用特定的权限。
一个掩码位为1表示阻止/禁用该权限(在该位上贴上胶带)。 一个掩码位为0表示允许该权限通过(在该位上没有胶带)。
因此,八进制022(000 010 010)的掩码意味着禁用“组写”和“其他人写”,并允许所有其他权限通过。
计算方法:
这是一个新文件的示例计算(默认666权限),使用022掩码:
  perm mask result
----------------------------
u 1    0    1 (pass through)
  1    0    1 (pass through)
  0    0    0 (pass through)
----------------------------
g 1    0    1 (pass through)
  1    1    0 (disable)
  0    0    0 (pass through)
----------------------------
o 1    0    1 (pass through)
  1    1    0 (disable)
  0    0    0 (pass through)

那就是当你创建一个新文件时,得到644的结果。
更简单的方法是使用符号化的umask表示法,如果反向掩码计算让你感到困惑的话。使用这种方法,你只需指定传递位而不是掩码位。 umask u=rwx,g=rx,o=rx 表示允许用户rwx、组rx和其他人rx通过。这意味着禁用组w和其他人w。如果你运行这个命令然后检查umask,你会得到022。 umask u=rwx,g=,o= 表示允许用户rwx通过。这意味着禁用组和其他人的所有访问权限。如果你运行这个命令然后检查umask,你会得到077。
额外的计算:
如果你真的想理解"八进制掩码是通过对参数的一元补码使用位非运算符进行计算"的含义,这里有一些逻辑表可以帮助演示。记住,掩码位1表示禁用,0表示通过。
perm mask result
----------------
0    1    0     (mask 1 always disables)
1    1    0     (mask 1 always disables)
0    0    0     (mask 0 passes through)
1    0    1     (mask 0 passes through)

如果你用NOT(mask)来制作表格,现在它只是一个简单的AND逻辑表格!
perm NOT(mask) result
---------------------
0    0         0     (mask 1 always disables)
1    0         0     (mask 1 always disables)
0    1         0     (mask 0 passes through)
1    1         1     (mask 0 passes through)

所以它的公式是:result = perm AND (NOT mask)

有时候,一个问题可能已经存在超过10年,但仍然没有一个能满足你口味的答案,所以我要发表自己的观点。每个创建文件(或目录)的过程都会给这些文件赋予一组默认的读/写/执行权限。虽然我们在这里使用了“默认”这个词,但它并不意味着一个“固定的默认值”,也就是说,它可以改变,就像我们可以通过修改配置值来改变程序的行为一样。
在“菜鸟”的世界中,有一种流行的错误观念认为新创建的文件和目录有一些“固定的默认”权限值(例如664和775,有时是755和644等)。虽然这些数字可以是默认权限值,但正如我们之前所说,它们并不是固定的(八进制)数字。它们对于每个进程可能是不同的。
所以,计算每个进程的默认权限的实际公式是什么呢?对于目录来说,它是0777 & <进程掩码>,对于文件来说,它是0666 & <进程掩码>(在这两种情况下,&运算符是按位与运算,也就是说,它可以关闭0777中的某些位,但不会打开任何位。它既不是取反也不是减法,而是按位与运算)。
注意1:`man umask`没有给出第二个公式(用于文件),但不用担心,它是正确的。
注意2:允许文件默认具有执行权限存在合法的安全问题。因此,系统通常配置为删除文件的执行权限,因此上述第二个公式中的0666。但是,目录需要执行权限才能进行导航。也就是说,例如,如果`/home/`具有`r`权限,则可以使用`ls`命令查看其内容,但是如果没有`x`权限,则无法使用`ls /home/$USER`命令。

注意事项3。要为进程“设置”掩码,请使用umask <proper-value>命令。要获取进程的掩码,请单独使用umask命令,不带任何参数,例如,在我的终端中运行时会得到0022。


让我理解umask工作原理的最简单的答案是:

设置的掩码位指定要关闭的权限位。

例如:

umask 007

  • 所有用户和组位都关闭,因此它们不起作用。
  • 所有全局位都打开,因此它们关闭所有权限位。

因此,umask对文件权限644的影响是:

  • 0000b):保持用户位不变
  • 0000b):保持组位不变
  • 7111b):关闭所有全局位

结果是权限640