Linux umask 不是减法:用三个创建实验看懂默认权限

举报
yd_237867988 发表于 2026/10/28 11:34:57 2026/10/28
【摘要】 通过两个文件和一个目录的可复现实验,解释 umask 的按位屏蔽、请求权限的边界、已有文件为何不受影响,并给出后台服务与默认 ACL 的排查顺序。

在云服务器上排查权限时,常见现象是:同一个目录,手工创建的文件能读,服务创建的文件却读不了。先别急着执行 chmod -R 777;创建者请求的权限、进程的 umask 和目录 ACL,往往已经足以解释差异。

一、先预测,再运行

下面的实验只在临时目录里创建两个空文件和一个子目录,不需要 root,也不会修改系统配置。请在单独的 Python 进程执行,不要粘贴到正在运行的多线程服务中。

把进程 umask 设置为八进制 027 后,预测这三种创建请求的结果:普通文件请求 666、私有文件请求 600、目录请求 777。

本文的代码已在本地 macOS 的普通临时目录运行,实际输出见下方;Linux 规则另对照 Linux man-pages 的 umask(2) 手册核对。Linux 云主机上的实际结果还需结合文件系统与 ACL 配置验证。

二、完整复现代码

import os
import tempfile

with tempfile.TemporaryDirectory(prefix="umask-demo-") as root:
    previous = os.umask(0o027)
    try:
        for name, requested in [("normal.txt", 0o666),
                                ("private.txt", 0o600)]:
            path = os.path.join(root, name)
            fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_WRONLY,
                         requested)
            os.close(fd)

        os.mkdir(os.path.join(root, "data"), 0o777)
        for name in ["normal.txt", "private.txt", "data"]:
            mode = os.stat(os.path.join(root, name)).st_mode & 0o777
            print(name, oct(mode))

        os.umask(0o077)
        mode = os.stat(os.path.join(root, "normal.txt")).st_mode & 0o777
        print("existing normal.txt after umask 077", oct(mode))
    finally:
        os.umask(previous)

本地输出:

normal.txt 0o640
private.txt 0o600
data 0o750
existing normal.txt after umask 077 0o640

代码用 O_EXCL 确保只创建新文件;TemporaryDirectory 离开作用域后清理本次实验文件。finally 恢复进程原来的掩码,避免后续创建操作意外沿用测试值。

三、为什么 600 没有变成 573

在没有父目录默认 ACL 等额外影响时,只讨论九个普通权限位,计算式是:

实际权限 = 请求权限 & (~umask & 0777)
0666 & 0750 = 0640
0600 & 0750 = 0600
0777 & 0750 = 0750

027 中的 2 是屏蔽所属组的写权限,7 是屏蔽其他人的全部权限。它只能清掉请求中已有的位,不会凭空增加权限。600 本来就没有组和其他人权限,所以仍然是 600。把 umask 当八进制减法,会在这种例子里算错。

文件是否有执行位,也取决于创建请求:666 原本不含执行位,掩码再宽松也不会把它变成可执行文件。

最后一行输出说明另一个边界:修改 umask 不会回头改已有文件。处理已有文件需要另外评估 chmod 或 ACL,不能靠修改登录配置期待历史文件自动更新。

四、把实验变成排查步骤

  1. 先确认文件是谁创建、何时创建,检查拥有者和组,而不是只看最后三位数字。
  2. 区分新建与覆盖:应用直接写入已有文件,和先写临时文件再替换,可能得到不同结果。确认实际写入方式后再解释权限变化。
  3. 在创建进程的上下文核对 umask。交互式终端的设置不能直接代表后台服务;服务配置变更后,用新进程创建的测试文件验证。
  4. Linux 上若计算结果仍对不上,检查父目录默认 ACL。默认 ACL 存在时,不能仅用上面的简化公式推算;普通 mode 输出也不能展示完整 ACL 信息。

选择默认权限前,先明确谁必须读取、谁必须写入。比如 027 适合“所有者可写、同组可读、其他人无权”的某些场景,但应用若主动请求 600,同组依然读不到;它也不是所有服务都适用的通用配置。

规则参考:Linux man-pages,umask(2),DESCRIPTION 与 NOTES;本地可通过 man 2 umask 查询。实验代码和输出为本文自行编写与执行。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。