【问题标题】:os.Mkdir and os.MkdirAll permissionsos.Mkdir 和 os.Mkdir 所有权限
【发布时间】:2013-01-10 01:33:50
【问题描述】:

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

如果/log 目录没有创建目录,我需要检查它是否存在,然后继续创建日志文件。

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

谢谢!

【问题讨论】:

    标签: linux go


    【解决方案1】:

    你可以直接使用八进制:

    os.Mkdir("dirname", 0700)
    


    权限位

    +-----+---+--------------------------+
    | 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 |
    +------------+------+-------+
    

    A Unix Permission Primer


    常见权限用法

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

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

    0644 只有所有者才能读写。其他人只能阅读。没有人可以执行该文件。

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

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


    Linux 上的目录权限

    在 Linux 上对目录应用权限时,权限位的含义与常规文件不同。 (source)

    读取位用户可以读取目录中包含的文件名。
    写入位用户可以{添加、重命名、删除}文件名,如果执行位也设置了。
    执行位用户可以进入目录并访问里面的文件。

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

    权限计算器

    方便的permissions calculator

    【讨论】:

    • 我不明白您显然是如何理解 unix 权限的,给出了解释,但仍然说“在某些情况下,您需要设置 777 权限才能上传任何权限文件到服务器(例如,在 WordPress 中上传图片)”不!除非在极少数情况下(例如/tmp,但设置了sticky 位,因此它不一样),否则您永远不需要。如果您需要上传东西,则将目录的用户设置为运行网络服务器或PHP的用户。够了。无需随机用户或 MTA 或任何能够写入此目录的东西
    • 我写了一个brief introduction here,它应该涵盖大部分基础知识(我正在开发一个更扩展的版本)...在 Wordpress 示例中,您需要将上传目录设置为需要写入的用户(即运行php或网络服务器的用户),并将其设置为755,以便只有该用户可以写入。跨度>
    • 这个答案对权限值之前的额外0 的要求视而不见。有人可以谈谈并将其添加到答案中吗?
    • 另外值得注意的是目录需要 execute 权限。这是一个奇怪的 Unix 东西。
    • @Timmmm 目录需要执行权限才能cd进入。
    【解决方案2】:

    @Daniel 在他的回答中的陈述并不正确,而且它谈到了一个十进制数,然后使用了一个八进制数,正如@SashaCrofter 在他的评论中正确指出的那样。

    实际上,无论您的权限值是什么形式,只要它代表合理的 Unix 权限即可。

    由于 POSIX 文件系统上的权限位是由三位组成的——三位用于所有者、组和其他人的访问权限,加上三位修饰符(例如粘性位)——习惯上使用八进制数来表示每个位的权限八进制数中的digit表示三位值。

    因此,当你在 Go 代码中使用 0700 时,前导 0 会被去除,仅用于告诉解析器它看到一个八进制数字文字,以下三个字母代表所有者、组和其他权限,在此命令。如果您还想设置组粘性位以及使文件系统对象组可读和可执行,您可以指定 02750 等等。

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

    要更深入地了解这些主题,最好阅读chmod 手册页和有关类 Unix 操作系统的一般文献。

    【讨论】:

      【解决方案3】:

      您可以将 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
      

      【讨论】:

      • 这才是真正的答案
      【解决方案4】:

      除了其他答案,请记住,在 Unix 和 Linux 风格的操作系统上,所有程序都使用 umask 设置运行。 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:我真的不确定在哪里可以找到 简单 描述。不过,The Wikipedia umask page 有很好的信息。早在 1980 年代初,我就很难学会这些东西......
      【解决方案5】:

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

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

      我通常将os.ModePerm(实际上编码为0777)用于完全许可的目录,例如缓存或临时文件所需的目录,但您的里程可能会有所不同。要设置额外的位(粘性等),正如@kostix 所指出的那样,必须处理 Go 中标志的八进制表示问题,您总是可以使用类似的东西:

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

      Go playground

      与往常一样,值得一提的是再次这些权限被设置为umask 的任何“过滤”。

      【讨论】:

      • @nishanthshanmugham 非常感谢您发现我的愚蠢错误!呵! :-) 现在显示的答案非常正确。
      猜你喜欢
      • 1970-01-01
      • 2015-07-05
      • 1970-01-01
      • 2016-02-05
      • 2014-09-02
      • 2018-03-17
      • 2022-01-24
      • 2016-09-04
      • 2014-02-21
      相关资源
      最近更新 更多