Linux umask 不是减法:用三个创建实验看懂默认权限
在云服务器上排查权限时,常见现象是:同一个目录,手工创建的文件能读,服务创建的文件却读不了。先别急着执行 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,不能靠修改登录配置期待历史文件自动更新。
四、把实验变成排查步骤
- 先确认文件是谁创建、何时创建,检查拥有者和组,而不是只看最后三位数字。
- 区分新建与覆盖:应用直接写入已有文件,和先写临时文件再替换,可能得到不同结果。确认实际写入方式后再解释权限变化。
- 在创建进程的上下文核对 umask。交互式终端的设置不能直接代表后台服务;服务配置变更后,用新进程创建的测试文件验证。
- Linux 上若计算结果仍对不上,检查父目录默认 ACL。默认 ACL 存在时,不能仅用上面的简化公式推算;普通 mode 输出也不能展示完整 ACL 信息。
选择默认权限前,先明确谁必须读取、谁必须写入。比如 027 适合“所有者可写、同组可读、其他人无权”的某些场景,但应用若主动请求 600,同组依然读不到;它也不是所有服务都适用的通用配置。
规则参考:Linux man-pages,umask(2),DESCRIPTION 与 NOTES;本地可通过 man 2 umask 查询。实验代码和输出为本文自行编写与执行。
- 点赞
- 收藏
- 关注作者
评论(0)