如果路径已经存在并且模式已通过,path.mkdir() 是否会更新文件权限?

Does path.mkdir()'s updates the file permissions if path already exists and mode is passed?

我在 kubernetes 中附加了一个卷,路径为 /var/www/aaa/tmp

该卷是使用 path.mkdir() 创建的,目前拥有 755 权限。 它最初是用代码 path.mkdir(parents=True, exist_ok=True) 创建的。

我正在尝试在不删除现有路径的情况下更新其权限。

我正在使用 path.mkdir(parents=True, exist_ok=True, mode=0o777)。我仍然面临与创建上述目录的烧瓶应用程序的权限和获取 502 Bad gateway 相关的问题。

如果 path.mkdir(parents=True, exist_ok=True, mode=0o777) 已经存在并且具有 755 权限,是否更新路径权限?或者它会像我们提到的那样完全忽略它 exists_ok=True 吗?我没有看到路径的权限得到更新。

我是否应该完全删除路径并用 mode=0o777 重新 运行 path.mkdir..... 以创建新目录并设置权限?

编辑 1: 我试过在路径上使用 os.chmod() 。但它正在抛出 PermissionError.

这是代码片段。

path.mkdir(parents=True, exist_ok=True)
os.chmod(path, mode=0o777)

错误:

File "./app/init.py", line 79, in create_prediction_app create_directories(app) File "./app/init.py", line 36, in create_directories os.chmod(path, mode=0o777) PermissionError: [Errno 1] Operation not permitted: '/var/www/aaa/tmp' unable to load app 0 (mountpoint='') (callable not found or import error) * no app loaded. GAME OVER *

如果路径已经存在,您应该使用 os.chmod(path, mode) 而不是 deleting/re-creating。

例如:

import os

os.chmod("/var/www/aaa/tmp", 0o777)

另外,chmod可以得到stat模块的权限

  • stat.S_ISUID - 在执行时设置用户 ID。
  • stat.S_ISGID - 在执行时设置组 ID。
  • stat.S_ENFMT - 强制执行记录锁定。
  • stat.S_ISVTX − 执行后保存文本图像。
  • stat.S_IREAD − 所有者阅读。
  • stat.S_IWRITE − 所有者写的。
  • stat.S_IEXEC − 由所有者执行。
  • stat.S_IRWXU − 由所有者读取、写入和执行。
  • stat.S_IRUSR − 所有者阅读。
  • stat.S_IWUSR − 所有者写的。
  • stat.S_IXUSR − 由所有者执行。
  • stat.S_IRWXG − 按组读取、写入和执行。
  • stat.S_IRGRP − 分组阅读。
  • stat.S_IWGRP − 按组写。
  • stat.S_IXGRP - 按组执行。
  • stat.S_IRWXO − 由他人读取、写入和执行。
  • stat.S_IROTH − 其他人阅读。
  • stat.S_IWOTH − 别人写的。
  • stat.S_IXOTH − 由他人执行。

例如:

import os
import stat

# Set a file write by others.
os.chmod("/var/www/aaa/tmp", stat.S_IWOTH)

您可以使用按位运算符设置更多权限。

例如:

import os
import stat

os.chmod(
    '/var/www/aaa/tmp',
    stat.S_IRUSR |
    stat.S_IROTH |
    stat.S_IRGRP 
)

完成测试:

>>> touch test_perm.sh
>>> ll test_perm.sh
-rw-rw-r-- test_perm.sh
>>> python -c "import os; os.chmod('test_perm.sh', 0755)"
>>> ll test_perm.sh
-rwxr-xr-x test_perm.sh

编辑:

如果你想用os.chmod更改权限时出现PermissionError: [Errno 1] Operation not permitted:...异常,你应该尝试下面的代码部分来解决它。 运行 具有管理员权限的脚本很重要(sudo 在 Linux 环境中)。

代码:

from getpwnam import pwd
from getgrnam import grp
import os

uid = getpwnam("USERNAME")[2]
gid = grp.getgrnam("GROUPNAME")[2]
os.chown("/var/www/aaa/tmp", uid, gid)

基于官方 chown 文档:

os.chown(path, uid, gid, *, dir_fd=None, follow_symlinks=True)

Change the owner and group id of path to the numeric uid and gid. To leave one of the ids unchanged, set it to -1.

This function can support specifying a file descriptor, paths relative to directory descriptors and not following symlinks.

See shutil.chown() for a higher-level function that accepts names in addition to numeric ids.

Availability: Unix.

New in version 3.3: Added support for specifying path as an open file descriptor, and the dir_fd and follow_symlinks arguments.

Changed in version 3.6: Supports a path-like object.

Link 到文档:https://docs.python.org/3/library/os.html#os.chown

milanbalazs 的回答很好,很好的解释,但只会 chmod 路径中的最后一个目录。在我的例子中,这还不够好,因为我需要确保所有子文件夹一直到最后一个也被修改。

我找不到任何简单的方法来使用现有的 bash 工具来完成此操作,唯一接近我需要的工具是 chmod -R 但我也不想在没有除了路径中指定的每个文件夹之外的任何内容。

澄清一下,在示例中,我们有路径 /var/www/aaa/tmp。我可能想从 /var/www 开始,并确保 /var/www/aaa/var/www/aaa/tmp 都将它们的权限设置为我想要的任何值。

所以我写了下面的脚本来解决这个用例;

import os
import argparse

def base8(val):
    return int(val, base=8)

def path(val):
    assert os.path.exists(val)
    return val

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('start_dir', type=path, help='starting point for chmod to check for subdirectories')
    parser.add_argument('end_dir', help='last directory to be chmodded, relative to start_dir')
    parser.add_argument('permission', type=base8, help='permission to set on each directory (must be base 8 format e.g. "0o750")')

    args = parser.parse_args()
    return args

def main():
    args = parse_args()

    directories = os.path.split(args.end_dir)
    current_dir = args.start_dir
    for directory in directories:
        current_dir = os.path.join(current_dir, directory)
        os.chmod(current_dir, args.permission)

if __name__ == '__main__':
    main()

希望有一天有人会发现这有用:)