为什么在chmod命令中,777代表允许文件的所有操作?

在面试中有人问我为什么777被分配为文件的全部权限。为什么不是555呢?他说每个事物都有原因。那么,777的原因是什么?为什么不是其他任何数字?这个数字有特殊意义吗?


5请查看 https://help.ubuntu.com/community/FilePermissions - Avinash Raj
2请参考@AvinashRaj的链接评论,并将其应用于实例。问题“为什么?”取决于它是什么实例以及它所服务的目的... :) - AzkerM
1他是在问数字7和5的意义,还是为什么它们是数字而不是字母呢? - Braiam
4这是一个很棒的面试问题,我可能得借鉴一下。 - Digital Chris
1@DigitalChris 是为了筛选出那些连这个都不懂的人,对吧? :D 如果你不得不与他们打交道,我表示同情。 - mirabilos
1我以为有人只是碰巧过得很幸运。 - Justine Krejcha
5严格来说,不是777,而是0777。 - Ruslan
有一个关于八进制的SO问题似乎很相关:八进制数字面量:何时?为什么?永远?(已关闭)。那里有几个很好的答案。 - Ben Collins
虽然这并不是对你具体问题的回答,但如果你对深入了解这些东西的来源感兴趣的话,可以去看一下《Unix环境高级编程》这本书,其中包含了很多其他内容。这本书揭示了所有这些概念如何相互关联的基本原理,非常优雅。 - danp
6个回答

我会尝试解释为什么是777,而不是aaa或999的根本原因。
请记住权限的格式如下:
 u   g   o
rwx rwx rwx

其中,u=用户,g=组,o=其他。

现在,想象一下你将这些组表示为二进制。1代表true,0代表false。

如果你想给每个人完全访问权限,你会按照以下二进制分配权限:

 u   g   o
rwx rwx rwx
111 111 111

现在,如果你知道二进制,你会意识到当你把111从二进制转换为十进制时,得到7

因此,你可以把完全访问表示为777

注意:实际上我们是从二进制转换成八进制。请参见下面的编辑。

这对于所有其他访问模式也适用。

例如,我们可以通过将每个5转换为二进制并按照上述格式书写来轻松计算出555的含义。二进制中的5101,因此我们有以下权限:

 u   g   o
r-x r-x r-x
101 101 101
 5   5   5

同样地,如果我们想要给予用户所有权限,但只允许其他人阅读,我们可以找到一个数字表示。
 u   g   o
rwx r-- r--
111 100 100
 7   4   4

现在,我们知道二进制中的111等于十进制中的7,而二进制中的100等于十进制中的4。因此,权限将是744

编辑:

从技术上讲,如@LưuVĩnhPhúc和@Braiam所指出的那样,我们正在将二进制转换为八进制,如下所述。然而,小于8的十进制和八进制表示是相同的,所以对于具有3位数或更少的二进制数,十进制和八进制表示是相同的。

当作为八进制数表示时,不需要将其分成三组,并对每组进行二进制到十进制的转换,实际上可以将所有三个组一起作为一个单独的二进制数,并转换为八进制。

例如,这是一些二进制到八进制的转换:

0b111111111 == 0o777
0b101101101 == 0o555
0b111100100 == 0o744

请注意,我在二进制和八进制数字之前添加了"0b"和"0o"以区分它们。
如果你想尝试一下,请打开终端,运行"python",然后使用以下命令进行操作:
oct(0b111111111)
bin(0o555)

记得在数字前加上“0b”或“0o”,让计算机知道你感兴趣的进制。如果不这样做,它会默认为十进制。

17仅为完整起见,数字的格式被称为八进制,字面意思是8的基数(因为它们从0开始,所以是7+1=8)。 - Braiam
1好判断。我得承认,这个联想我自己没有想到过。 - daviewales
3Davie:八进制很简单,因为它实际上将三个位分组在一起,就像十六进制将四个位分组一样。十进制不是2的幂,所以不能像八进制和十六进制那样方便地分组位。 - Konerak
1当你将111从二进制转换成十进制时,你会意识到这是不正确的。它应该是"从二进制转换成八进制"。 - phuclv
2无论哪种情况,你都会得到相同的数字。我认为将二进制转换为十进制比将二进制转换为八进制更容易理解。另外,我在最后添加了一个部分来澄清这些数字实际上是八进制,而不是十进制。 - daviewales
1请注意,八进制表示法不仅限于9位。您还可以设置特殊位,例如经典的chmod 1777 /tmp以设置粘滞位。请参阅http://unix.stackexchange.com/questions/71622/what-are-common-rights-for-tmp-i-unintentionnally-set-it-all-public-recursive - Rmano
3在十进制和八进制中,数字7是相同的。然而,数字777则不同。当谈到翻转比特时,这就有了差别。 - Sam Dufel
2仅仅出于嬉闹的目的,数字7被称为上帝之数,而默认权限为777的根用户有时也被称为上帝。 - eyoung100
@SamDufel 我知道这个。我以为在编辑中已经表达得很清楚了... 如果没有的话,请告诉我你认为我应该怎么改进它。 - daviewales

读取文件权限表示为4,写入文件权限表示为2,执行文件权限表示为1

因此,总和为7

那么777是什么意思:第一个7是文件所有者的权限,这意味着文件所有者具有读取、正确和执行权限。

第二个7是文件所属的组,它表示该组也具有所有读取、写入和执行权限。

第三个7是其他人的权限。

如果您给文件权限555,则文件所有者、组和其他人只具有读取执行权限,没有写入权限,因为读取权限表示为4,执行权限表示为1,所以总共得到5


什么是群组,还有其他权限是什么?谢谢回复。 - hellodear
请参考此链接(http://www.udel.edu/it/help/unix/unixgroups.html)了解组及其他权限的详细信息,这些权限将对服务器上除您外的任何其他人或不属于您所在组的人生效。 - Prakash V Holkar

简单来说:

每个文件有3种权限选项:读取、写入和执行。你可以选择其中之一,两个,或者全部:

C(3,0) + C(3,1) + C(3,2) + C(3,3) = 8

1 + 3 + 3 + 1 = 8

所以,总共有8种组合;8种权限选项。从0开始计数,最后一个数字是7(从0到7)。因此,用数字表示,以下是所有的选项:

0 - nothing
1 - execute
2 - write
4 - read
3 - execute + write (1 + 2)
5 - execute + read (1 + 4)
6 - write + read (2 + 4)
7 - execute + write + read (1 + 2 + 4)

有三个数字是因为顺序是[用户权限][组权限][其他权限]。
所以,777意味着所有三个组都具有读取、写入和执行权限。
另外(间接相关,所以您不一定需要阅读这部分),为什么“读取”是4而不是3?我认为它的相关性很重要。
0 - nothing
1 - execute
2 - write
3 - read
4 - execute + read (1 + 3)
5 - write + read (2 + 3)
6 - execute + write + read (3 + 2 + 1)
7 - ????? no way to get this with the 3 basic options (and we are missing execute + write)

唯一获取所有可能性的独特组合的方法是按照基本选项的2的幂进行计算。20 = 1(执行),21 = 2(写入),22 = 4(读取),如果有第四个基本选项,它将被编号为23 = 8。请注意,在列出之前的所有组合中,没有列出"写入"(因为只有一个选项,即"执行")。在列出之前的所有组合中,也没有列出"读取"(再次只有一个组合,即"执行" + "写入")。在列出之前的所有组合中,也没有列出"执行" + "写入" + "读取",这是因为现在有三个权限中的两个选择,所以共有3种组合。无论有多少个基本选项,列表都会以这种方式继续下去。举例来说,假设有4个基本选项(请注意,我们也知道总共会有16种组合,因为有4个选项,24 = 16):
0 - nothing
1 - execute
2 - write
4 - read
3 - execute + write (1 + 2)
5 - execute + read (1 + 4)
6 - write + read (2 + 4)
7 - execute + write + read (1 + 2 + 4)
8 - love
9 - execute + love (1 + 8)
10 - write + love (2 + 8)
11 - execute + write + love (1 + 2 + 8)
12 - read + love (4 + 8)
13 - execute + read + love (1 + 4 + 8)
14 - write + read + love (2 + 4 + 8)
15 - execute + write + read + love (1 + 2 + 4 + 8)

6这个答案非常糟糕,因为它没有意识到二进制和更重要的八进制数字系统是Unix文件权限位的来源。(有趣的是,它们不是3或甚至4...它们是6,尽管目前并没有使用全部18位。) - mirabilos
1基数并不重要,因为111等于7;无论我说权限是111还是7都没关系,因为它们是相同的值。我使用十进制只是为了简单起见,以展示所涉及的数学运算。我本可以使用二进制,但数学并不那么直观。当基数之间可以相互转换时,这有什么关系呢? - Daniel Ward

我对这么多类似的答案完全偏离了问题感到惊讶。
在确定需要读取、写入和执行的3个类之后,他们选择了八进制(3位)来最小化管理文件系统所需的空间。

由于某种原因,UNIX设计者决定使用八进制数字来表示文件权限。正如您所知,一个一位数的八进制数字的最大值是7。事实证明,一个八进制数字足以表示用户访问权限、组访问权限和全局访问权限。最大的三位数八进制数字是777,这只能表示“对每个人/每件事都有访问权限”。

我不认为这是一个好的解释。UNIX设计者本来可以使用十进制数字,但最终仍然会选择用7表示最大访问权限,而不是9(作为最大的十进制数字)。这个7并不是根据从最高可能的个位数开始可能的数字进行“减法”选择的,而是根据从零开始的单个二进制数字所允许的访问权限进行“加法”选择的。 - O. R. Mapper
注意,我在一开始写了“出于某种原因”…… - 我不想深入解释为什么他们选择八进制数,因为这不是提问者的问题。问题是为什么777给予所有权限。 - DejanLekic
在这里,他们选择八进制数的原因并不重要。我的观点是,最大权限用数字7表示的原因不是因为7恰好是最大的八进制数。 - O. R. Mapper

如今,我们都知道一个字节等于8位:这个观点已经被广泛接受了几十年。但这并非一直如此,Unix(在许多方面启发了Linux)是在这个问题仍然存在争议的时候编写的。特别是,它需要能够在使用6位字节或8位字节的系统上移植。其中一些编写者站在辩论的一边,而其他人则站在另一边。
关于这个问题,二进制(Base-2)并不是一个很方便的表示法来写出数值。如今,大多数程序员使用更紧凑的十六进制(Base-16)表示法。16正好是一个足够大的基数,可以将四位二进制精确地打包成一个十六进制数字:例如,二进制中的"0000"在十六进制中表示为0x0("0x"是一种常见的表示即将写入十六进制数的方式),而"1111"则表示为0xF(或者十进制中的15)。实际上,你可以通过二进制计数来用单个十六进制数字写出任何可能的四位二进制组合,并且由于位置算术的工作原理,你可以堆叠起来:两个十六进制数字可以编码任何可能的八位组合,依此类推。因此,8位的人们喜欢这种表示法。
6位的人们有他们自己的方法来做这个,但是他们没有使用16进制,而是使用8进制(八进制)。它与十六进制有类似的优点:你可以在一个八进制数字中存储任意三位的位置,并且可以以类似的方式堆叠数字。所以就像8位的人们用两个十六进制数字表示一个字节一样,6位的人们用两个八进制数字表示一个字节。现在,你很少见到八进制了,但是通常会用前导零来表示:例如,“111”在八进制中表示为07。
现在,所有这些与Unix权限有什么关系呢?就Unix而言,对于一个文件,你可以进行三种操作:读取、写入或者将其作为程序执行。如果你要通过权限来限制这些操作,那么你需要为每个操作分配一个比特位:对于某些人被允许的操作,将其打开;对于某些人不被允许的操作,将其关闭。由于有三个操作需要跟踪,所以你需要三个比特位,而由于Unix沿着三条线(拥有者、组和其他人)跟踪它,所以总共需要九个比特位。
在某个时候,有人(可能是6位阵营的人)说:“嘿,我们可以用八进制数字来表示这个”。结果证明,这是一种非常方便的表示法:三个八进制数字足以编码所有可能的位字段组合。一旦他们决定这样做,777和000的命运就注定了,因为无论他们如何排列位,这些数字都将保持不变,但对于其他所有数字,顺序都很重要,所以他们开始着手处理这个问题。
他们将权限分成了三个位字段:读取位在开头,写入位在中间,执行位在末尾。然后,他们安排了字段本身的顺序:所有者在开头,群组在中间,其他人在末尾。一旦他们完成了这个步骤,他们只需要继续计数来分配剩下的数字。
因为它们是3位二进制字段,所以可以说每个八进制数字控制一个字段:第一个数字控制所有者权限,第二个数字控制组权限,第三个数字控制其他用户权限。因此,777(111 111 111)表示所有人的所有权限,而700(111 000 000)表示仅所有者具有所有权限。还有其他常见的组合:666(110 110 110)表示所有人都可以读写但不能执行,而555(101 101 101)表示所有人都可以读取和执行但不能写入,400(100 000 000)表示仅所有者具有只读权限,其他人没有访问权限。
这就是为什么777表示所有权限。如今,这可能是人们使用八进制的最流行原因,尽管Unix及其后代仍保留了一些其他遗留功能。例如,Octal Dump(od)是一种以八进制形式获取文件的二进制转储的方法(它还有一个十六进制版本,称为xxd,但不太知名且不是在所有地方都可用)。这也是为什么在某些编程语言中需要小心处理前导零的原因,因为它们可能会认为你打算以八进制写入数字,而这并不是你真正的意图。

首先,当Linux诞生时(大约1992年),8位和6位的争论早已结束。其次,这并不是做出这个决定的原因。 - Ahmed Masud
1我提供了8位/6位的内容,以便提供历史背景。Linux在那场辩论结束很久之后才诞生,这是事实,但由于它从Unix中汲取了很多灵感,所以它也受到了类似的影响。这就是为什么我认为介绍历史背景是个好主意的原因。 - The Spooniest