os.Mkdir 和 os.MkdirAll 权限

106

我正在尝试在程序开始时创建一个日志文件。

我需要检查是否存在一个名为/log的目录,如果不存在则创建该目录,然后继续创建日志文件。

我试过使用os.Mkdir(以及 os.MkdirAll ),但无论我将什么值放入第二个参数中,都会得到一个没有权限的锁定文件夹。为了获得用户文件夹的读/写权限,这个值应该是多少呢?我认为应该是0x700,但似乎不起作用。

谢谢!

5个回答

169
你可以直接使用八进制表示法:
os.Mkdir("dirname", 0700)

权限位

权限位通常以八进制表示,因此字面值必须以0作为前缀。否则,它将被解释为十进制并产生混淆的结果。这与Linux命令chmod保持一致。

+-----+---+--------------------------+
| rwx | 7 | Read, write and execute  |
| rw- | 6 | Read, write              |
| r-x | 5 | Read, and execute        |
| r-- | 4 | Read,                    |
| -wx | 3 | Write and execute        |
| -w- | 2 | Write                    |
| --x | 1 | Execute                  |
| --- | 0 | no permissions           |
+------------------------------------+

+------------+------+-------+
| Permission | Octal| Field |
+------------+------+-------+
| rwx------  | 0700 | User  |
| ---rwx---  | 0070 | Group |
| ------rwx  | 0007 | Other |
+------------+------+-------+

Unix权限入门

常见权限用法

0755 常用于Web服务器。所有者可以读取、写入和执行。其他人可以读取和执行,但不能修改文件。

0777 所有人都可以读取、写入和执行。在Web服务器上,不建议对文件和文件夹使用“777”权限,因为它允许任何人向服务器添加恶意代码。

0644 只有所有者可以读取和写入。其他人只能读取。无法执行该文件。

0655 只有所有者可以读取和写入,但不能执行该文件。其他人可以读取和执行,但不能修改文件。

www.maketecheasier.com/file-permissions-what-does-chmod-777-means/

Linux上的目录权限

在Linux上应用目录权限时,权限位的含义与普通文件不同。(来源

读取位 用户可以读取目录中包含的文件名。
写入位 用户可以添加、重命名、删除文件名,但必须同时设置执行位。
执行位 用户可以进入目录并访问其中的文件。

https://unix.stackexchange.com/a/21252

权限计算器

permissions calculator

一个方便的权限计算器

11
我不明白你为什么能很明显地理解 Unix 权限的解释,但仍然说“在某些情况下,你需要将权限设置为 777 才能将任何文件上传到服务器上(例如,在 WordPress 中上传图片)”。不!除了极少数情况(如 /tmp,但它有设置“粘滞位”,所以不同),你永远不需要这样做。如果你需要上传东西,那就将目录的用户设置为运行 Web 服务器或 PHP 的用户即可。这已经足够了。不需要让随机用户或 MTA 或其他任何人都能够写入此目录。 - Martin Tournoij
1
我在这里写了一个简短的介绍,它应该涵盖了大部分基础知识(我正在编写更详细的版本)... 在WordPress示例中,您需要将上传目录设置为需要写入它的用户(即运行php或Web服务器的用户),并将其设置为755,以便该用户可以写入它。 - Martin Tournoij
2
这个答案忽略了在权限值之前需要额外的 0 的要求。有人能谈一下并将其添加到答案中吗? - Shadoninja
2
值得注意的是,目录需要执行权限。这是一个奇怪的Unix事情。 - Timmmm
2
@Timmmm 目录需要执行权限,这样你才能 cd 进入其中。 - yusufmalikul
显示剩余5条评论

26

@Daniel 在他的答案中所说并不正确,并且在谈论十进制数字后使用了一个八进制数字,正如 @SashaCrofter 在评论中正确指出的那样。

事实上,只要代表合理的Unix权限,您的权限值的形式并不重要。

由于POSIX文件系统上的权限位以三位一组的方式表示,即三个位用于所有者、组和其他访问权限,再加上三个位的修饰符(例如粘性位),因此通常使用八进制数来表示权限,因为八进制数中每个数字都代表了一个三位二进制值。

因此,当您在Go代码中使用0700时,前导的0会被剥离,并且只是用来告诉解析器它看到了一个八进制数文字,接下来的三个数字依次代表所有者、组和其他权限。如果您想设置组粘性位以及使文件系统对象可读和可执行,可以指定02750等。

请注意,文件系统对象获得的实际权限还受创建该对象的进程的活动umask的调节。

要更好地掌握这些主题,最好阅读“chmod”手册页面和有关类Unix操作系统的文献。


21

您可以将umask重置为0。我会在我的主文件中首先进行这个调用。

syscall.Umask(0)

例子

_ = os.MkdirAll("/tmp/dirs/1", 0664)
syscall.Umask(0)
_ = os.MkdirAll("/tmp/dirs/2", 0664)

结果

/tmp/dirs$ stat -c '%A %a %n' *
drw-r--r-- 644 1
drw-rw-r-- 664 2

2
这是真正的答案。 - danthegoodman
我认为使用“0744”是最好的选择。 - decadenza

13
除了其他答案之外,请记住,在Unix和Linux风格的操作系统上,所有程序都在一个 umask 设置下运行。在许多情况下,默认值为022,有时是002,并且这是系统将从文件和目录创建请求中自动删除的权限集。
这意味着大多数程序 - 这个规则有几个例外 - 应该使用模式0666来创建文件,使用模式0777来创建目录。用户的配置记录在正在运行的进程中,指定了要去除哪些权限。如果用户的设置是022,并且我们使用模式0666创建文件,则实际设置我们得到的是rw-r--r--:对于用户而言是可读写,对于组只读,对于其他人也只读。
如果用户希望将可写性扩展到他们的组,他们只需要将其umask设置为2:现在他们取走其他人的写权限,但保留它们的组的写权限。新文件现在使用模式rw-rw-r--创建。程序不会改变:它仍然使用0666作为其模式。但是,文件将使用模式0664创建。
同样,如果使用0777调用os.Mkdiros.MkdirAll,那么umask将去除不需要的权限,留下正确的权限。

但是我提到过有例外情况。包括只为用户制作副本的敏感信息的程序:这些应该通常使用0700模式用于目录和0600用于文件。它们可能包括长时间运行的服务器,其作为系统用户而不是任何一个个人...虽然那些服务器可以以正确的umask运行,在这种情况下,07770666是可以接受的。

你必须在此应用一些判断。特别注重安全性的程序(如ssh或类似程序)可能希望使用有限的权限,甚至可能想要检查(使用os.Lstat或类似方法),以确保重要目录的权限适当紧密。

(请注意,umask 并不适用于 os.Chmod调用。在这里,直接选择模式。)


很好的解释。如果您能够添加一些源,其中他们以与您类似简单的方式写出这些想法,我将不胜感激。 - Mike
1
@Mike:我真的不确定在哪里找到简单的描述。维基百科umask页面有很好的信息。不过,我是在20世纪80年代初艰难地学习这些东西的... - torek

5

为了确保您设置了所需的权限,而不需要计算八进制的复杂计算,一种方法是使用包 os 中非常方便的 FileMode 常量:

https://golang.org/pkg/os/#FileMode

通常我会使用 os.ModePerm(实际上编码为 0777)用于完全开放的目录,例如需要缓存或临时文件的目录,但这取决于你的具体情况。如果要设置额外的位(如sticky等),可以像以下代码示例一样添加标志来进行设置:

if err := os.MkdirAll("my/tmp/dir", os.ModeSticky|os.ModePerm); err != nil {
  ... handle error ...
}

Go playground

值得一提的是,这些权限总是会受到已设置的umask的“过滤”。


@nishanthshanmugham非常感谢你发现了我的愚蠢错误!哈哈! :-) 现在显示的答案是完全正确的。 - Gwyneth Llewelyn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接