umask真实计算方式是位运算:实际权限=默认权限 & (~umask),文件默认0666、目录默认0777;内核强制过滤文件执行位,故文件永不带x权限。

umask 值怎么算出来的?别直接减 666 和 777
很多教程说“文件默认 666,减 umask 得实际权限”,这在多数情况下能蒙对,但底层逻辑是错的。真实计算用的是位运算:实际权限 = 默认权限 & (~umask)。关键点在于:文件默认权限其实是 0666(不是十进制 666),目录是 0777;而 umask 是按位取反后再与,默认权限做 AND 运算。
比如 umask 0022:
- ~0022 在八进制下等价于 ~0000010010₂ → 1111101101₂ → 八进制
0755(注意:这是掩码取反结果,不是最终权限) - 文件:
0666 & 0755 = 0644 - 目录:
0777 & 0755 = 0755
之所以文件不会出现执行位(x),是因为内核强制过滤掉文件的 x 位——哪怕你设 umask 0000,新建文件仍是 0666,不是 0777。这点和目录不同,目录必须保留 x 才能进入。
临时改 umask 后新建文件权限没变?检查当前 shell 类型
运行 umask 0002 后立刻 touch testfile,发现权限还是 -rw-r--r--(644),不是预期的 -rw-rw-r--(664)?大概率是你在非交互式 shell 或子 shell 里操作了。
umask 是 shell 内建命令,只影响当前 shell 及其派生进程。常见踩坑场景:
- 你在脚本里写了
umask 0002,但脚本执行完就退出,父 shell 不受影响 - 你用
sh -c "umask 0002; touch a",umask只在sh -c的那一瞬间生效,touch继承该 umask,但之后无法验证 - 你用
sudo bash切换后改 umask,但普通用户 shell 没变
验证是否生效,始终在**同一终端、同一 shell 进程**里执行:umask 0002 && touch x && ls -l x。
永久设置 umask,为什么改了 ~/.bashrc 还不生效?
写入 umask 0002 到 ~/.bashrc 后,新打开终端仍显示 0022?问题通常出在加载顺序或 shell 类型上。
Linux 登录时,shell 加载配置有优先级:
- 登录 shell(如 SSH 登录、图形终端首次启动):先读
/etc/profile→~/.bash_profile(或~/.profile)→ 最后才可能 source~/.bashrc(取决于前者的配置) - 非登录交互 shell(如 GNOME 终端新标签页):通常只读
~/.bashrc
所以如果你只改了 ~/.bashrc,但系统用的是 ~/.bash_profile 启动,那就不会加载。解决方法:
- 检查
~/.bash_profile是否存在且包含source ~/.bashrc - 或者直接把
umask 0002写进~/.bash_profile(更可靠) - 确认 shell 类型:
echo $SHELL,如果是zsh,要改~/.zshrc
改完务必用 source ~/.bash_profile 测试,别只靠新开终端——新开终端可能还缓存旧环境。
umask 设成 077 后,TAB 补全失效、history 不保存?别关 root 权限
设 umask 077 后,突然发现命令补全(TAB)报错、history 不记录、甚至某些服务启动失败?这不是偶然。
根本原因是:很多 shell 功能依赖临时文件或状态文件(如 ~/.bash_history、/tmp/xxx、~/.inputrc),它们由 shell 自动创建。若 umask 过严,这些文件会被创建为 600 或 700,但某些组件(如 readline 库、dbus session)在访问时会因权限不足静默失败。
更隐蔽的问题:
-
umask 077下,mkdir创建的目录是700,但如果你在共享目录(如/var/www)工作,协作方完全无法进入 - systemd 用户服务会读取
~/.config/systemd/user/下的 unit 文件,若该目录权限是700但 umask 是077,新生成的 socket 文件可能被拒绝访问
安全 ≠ 越严越好。生产环境推荐 002(协作)或 022(通用),077 仅适用于高度隔离的专用账户,且需同步检查所有依赖组件的权限兼容性。


















