【问题标题】:How can I get the default file permissions in Python?如何在 Python 中获取默认文件权限?
【发布时间】:2011-11-01 07:47:00
【问题描述】:

我正在编写一个 Python 脚本,在该脚本中我将输出写入一个临时文件,然后在完成并关闭该文件后将该文件移动到其最终目的地。脚本完成后,我希望输出文件具有与通过open(filename,"w") 正常创建的权限相同的权限。实际上,该文件将具有 tempfile 模块用于临时文件的一组限制性权限。

如果我在适当位置创建输出文件,我有没有办法弄清楚输出文件的“默认”文件权限是什么,以便在移动临时文件之前将它们应用到临时文件?

【问题讨论】:

标签: python file-permissions temporary-files


【解决方案1】:

记录一下,我遇到了类似的问题,这是我使用的代码:

import os
from tempfile import NamedTemporaryFile

def UmaskNamedTemporaryFile(*args, **kargs):
    fdesc = NamedTemporaryFile(*args, **kargs)
    # we need to set umask to get its current value. As noted
    # by Florian Brucker (comment), this is a potential security
    # issue, as it affects all the threads. Considering that it is
    # less a problem to create a file with permissions 000 than 666,
    # we use 666 as the umask temporary value.
    umask = os.umask(0o666)
    os.umask(umask)
    os.chmod(fdesc.name, 0o666 & ~umask)
    return fdesc

【讨论】:

  • 使用os.umask(0) 是一个潜在的安全问题,请参阅bugs.python.org/issue21082
  • 谢谢!我不知道这个问题(我感到羞耻)。我已经更新了答案。你还好吗?
  • 我自己不确定最佳方法,但至少这不会留下全局可写文件的风险。感谢您更新您的答案,没有理由感到羞耻:您的原始答案基本上是每个人都推荐的,而我也刚刚了解了这个问题。
【解决方案2】:

有一个函数umask in the os 模块。您无法获取当前的 umask 本身,您必须设置它并且函数返回之前的设置。

umask 继承自父进程。它描述了在创建文件或目录时设置哪些位。

【讨论】:

  • 那么,我是否应该使用任何值调用os.umask 一次,保存返回值,然后使用该值再次调用它以恢复它,然后从该掩码中获取适当的权限?
  • 为什么您只对 umask 的内容感兴趣,而不对它应该是什么 感兴趣?
  • 您确定要使用tempfile吗?
  • 嗯,tempfile 模块的优点是它为您提供了一个保证不存在的文件名。
  • @hop 这是一个合法的任务。例如,在安全方面,可能需要检查 umask 是否过于宽松。任务本身可能不是修复弱 umask,而是报告它。静默修复它可以掩盖用户在锁定系统上有意/无意共享文件的问题。
【解决方案3】:

这种方式速度慢但安全,适用于任何具有 'umask' shell 命令的系统:

def current_umask() -> int:
  """Makes a best attempt to determine the current umask value of the calling process in a safe way.

  Unfortunately, os.umask() is not threadsafe and poses a security risk, since there is no way to read
  the current umask without temporarily setting it to a new value, then restoring it, which will affect
  permissions on files created by other threads in this process during the time the umask is changed.

  On recent linux kernels (>= 4.1), the current umask can be read from /proc/self/status.

  On older systems, the safest way is to spawn a shell and execute the 'umask' command. The shell will
  inherit the current process's umask, and will use the unsafe call, but it does so in a separate,
  single-threaded process, which makes it safe.

  Returns:
      int: The current process's umask value
  """
  mask: Optional[int] = None
  try:
    with open('/proc/self/status') as fd:
      for line in fd:
        if line.startswith('Umask:'):
          mask = int(line[6:].strip(), 8)
          break
  except FileNotFoundError:
    pass
  except ValueError:
    pass
  if mask is None:
    import subprocess
    mask = int(subprocess.check_output('umask', shell=True).decode('utf-8').strip(), 8)
  return mask

【讨论】:

    【解决方案4】:
    import os
    
    def current_umask() -> int:
        tmp = os.umask(0o022)
        os.umask(tmp)
        return tmp
    

    此功能在一些 python 包中实现,例如pipsetuptools

    【讨论】:

      猜你喜欢
      • 2019-10-25
      • 2010-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多