第 5 章 · 05 默认权限: 本节摘要:前四节你学会了「读权限、改权限、定身份」。但有一个看似简单却少人深究的问题:当你 时,它的权限是怎么来的?为什么是 而不是 ? 答案在 这个「权限掩码」里。新建文件的权限 = 「全权限」减去 : 对应文件 、目录 。本节要把这套「反向计算」讲透——为什么用「掩码」(减法)而不是「直接给默认值」(加法)?因为安全默认原则:Linux 希望「默认情况下不给其他用户写权限」,用掩码能保证即使程序想给满权限,系统也会替你拦一道。理解 ,你才能在脚本里精确控制产物文件的权限。 内容来源:原项目「Linux 命令大全」 ,精选并套用体系化模板。 学习目标 阅读完本节,你应当能够: 说清 的作用:它是「权限掩码」,新建文件/目录的权限 = 全权限减去 。
umask本节摘要:前四节你学会了「读权限、改权限、定身份」。但有一个看似简单却少人深究的问题:当你
touch new.txt时,它的权限是怎么来的?为什么是644而不是777? 答案在umask这个「权限掩码」里。新建文件的权限 = 「全权限」减去umask:umask 022对应文件644、目录755。本节要把这套「反向计算」讲透——为什么用「掩码」(减法)而不是「直接给默认值」(加法)?因为安全默认原则:Linux 希望「默认情况下不给其他用户写权限」,用掩码能保证即使程序想给满权限,系统也会替你拦一道。理解umask,你才能在脚本里精确控制产物文件的权限。
内容来源:原项目「Linux 命令大全」
command/umask.md,精选并套用体系化模板。
阅读完本节,你应当能够:
umask 的作用:它是「权限掩码」,新建文件/目录的权限 = 全权限减去 umask。umask 022 对应的新文件权限(644)和新目录权限(755)。666 而不是 777(出于安全,默认不给执行位)。umask 命令查看当前掩码(umask)和临时修改掩码(umask 077)。设想两种设计思路:
default_perm,新建文件就赋这个权限。比如设成 default_perm=644,新文件就是 644。umask,新建文件权限 = 全权限减去 umask。比如 umask=022,新文件 = 666 - 022 = 644。表面看结果一样,但**「掩码」设计有一个微妙的安全优势**:程序在创建文件时可以指定「我希望这个文件权限是 X」(比如 open("f", 0666)),而 umask 会在程序指定的基础上再砍掉一层。这意味着:
open("f", 0666) 想给所有人写权限,只要系统 umask 是 022,实际创建出来的文件就是 644,其他用户拿不到 w。umask 是「系统级兜底」,不管程序怎么写,默认都保守。关键概念:
umask是「权限的反向过滤器」——它不是「给多少权限」,而是「默认拦掉多少权限」。这种「从满权限开始减」的设计,保证了「默认安全」:宁可权限不够让用户手动加,也不能默认就给太多。
在算 umask 之前,先明确「全权限」是多少:
777(rwxrwxrwx):目录天然需要 x 才能进入,所以全权限包含 x。666(rw-rw-rw-):文件默认不给执行位——执行位是危险的(能跑代码),需要时必须显式 chmod +x,不能默认给。💡 技巧:为什么文件默认不带
x?因为「可执行」是一个明确的「使用意图」,你应该主动声明「这是个脚本/程序」,而不是系统替你猜。这就是为什么你写个script.sh后必须chmod +x才能跑——umask也拦了一道(哪怕umask=000,新文件最多也是666,不会有x)。
新文件权限 = 666 & ~umask (按位与 + 按位取反) 新目录权限 = 777 & ~umask
实务上用「减法」近似理解即可(下文解释为什么是「近似」):
新文件权限 = 666 - umask (大多数 umask 数值下成立) 新目录权限 = 777 - umask
$ umask 022 $ umask -S # 符号式显示: u=rwx,g=rx,o=rx u=rwx,g=rx,o=rx
umask 不带参数,显示当前掩码(通常是 022 或 002)。-S 给出符号式,更直观。
umask 022$ umask 022 $ touch new.txt $ ls -l new.txt -rw-r--r-- ... new.txt # 644 $ mkdir newdir $ ls -ld newdir drwxr-xr-x ... newdir # 755
手算过程:
666 - 022 = 644(rw-r--r--)777 - 022 = 755(rwxr-xr-x)这是大多数 Linux 发行版的默认 umask。它意味着:新建文件对其他人只读,新建目录对其他人可进可读不可改——典型的「保守默认」。
$ umask 077 # 只允许自己访问 $ touch secret.txt $ ls -l secret.txt -rw------- ... secret.txt # 600: 只有属主能读写 $ umask 022 # 改回默认(只影响当前 shell 会话)
umask 077 是处理敏感数据时的常用设置——新建的文件就只有自己能访问,不需要再手动 chmod 600。这种「临时改 umask → 创建文件 → 改回 umask」是脚本里保护敏感产物的标准模式。
#!/bin/bash old_umask=$(umask) # 保存原 umask umask 077 # 收紧 echo "password" > /tmp/cred.txt # 创建的文件自动是 600 umask $old_umask # 恢复
这在脚本里创建临时密钥、凭证文件时极其有用——不依赖手动 chmod,创建瞬间就安全。
umask 002多用户系统用 022(防止其他用户乱动),单用户系统(如个人电脑)常用 002——让「同组用户」可写,便于同组协作:
$ umask 002 $ touch shared.txt $ ls -l shared.txt -rw-rw-r-- ... shared.txt # 664: 属主和属组都能写
002 适合「同一项目组、互相信任」的场景;022 适合「默认不信任其他用户」的服务器场景。
把常见的 umask 值整理成对照表,方便选择:
| umask | 新文件 | 新目录 | 适用场景 |
|---|---|---|---|
022 |
644 |
755 |
服务器默认,其他人只读 |
002 |
664 |
775 |
单机/团队协作,同组可写 |
077 |
600 |
700 |
处理敏感数据,其他人完全无权 |
007 |
660 |
770 |
同组完全共享,其他人无权 |
000 |
666 |
777 |
不推荐,所有人可写(仅极特殊场景) |
💡 技巧:生产环境脚本处理凭证、密钥时,临时切到
077——创建的文件自动是600,无需额外chmod,也不怕忘记。这是「安全默认」思维的应用。
理解 umask 最好的方式是动手实验,观察不同 umask 下创建文件的差异:
$ umask # 看当前 022 $ touch a.txt; ls -l a.txt # 644 -rw-r--r-- a.txt $ umask 077 $ touch b.txt; ls -l b.txt # 600 -rw------- b.txt $ umask 000 $ touch c.txt; ls -l c.txt # 666 (注意: 不是 777, 文件默认无 x) -rw-rw-rw- c.txt $ mkdir d; ls -ld d # 777 (目录默认有 x) drwxrwxrwx d
注意 umask 000 时文件是 666 而不是 777——这验证了「文件全权限是 666」的设计。即使你把 umask 全开,新建的普通文件也不会有执行位,必须显式 chmod +x。这是 Linux 的双层安全保护:umask 拦一道 + 文件类型限制拦一道。
web 服务、数据库等服务创建的文件权限,受服务启动时的 umask 影响:
# systemd 服务可以在 unit 文件里指定 umask [Service] UMask=007 # 该服务创建的文件属组可读写, 其他无权 ExecStart=/usr/bin/myservice
# 传统 init 脚本在开头设 umask 027 # 属组只读, 其他无权
这是运维调权限的高级手段——不靠事后 chmod,而是从源头控制服务创建文件的权限。理解 umask 才能读懂这些配置。
$ umask 022 # 新手误以为: umask 022 = 新文件权限是 022(??) # 实际: 新文件权限 = 666 - 022 = 644
umask 是「拦掉的权限」,不是「给的权限」。umask 022 意思是「拦掉其他的 w」(022 中第一个 0 是属主位,第二个 2 是属组位——等等,这里有个易错点,见下)。
实际上 022 三位分别对应 u/g/o:
0(属主):拦掉 0,即属主全权(rwx 或 rw)2(属组):拦掉 2(w),即属组 r-x 或 r--2(其他):拦掉 2(w),即其他 r-x 或 r--⚠️ 注意:
umask的每一位是「要拦掉的权限和」:0=不拦、1=拦x、2=拦w、3=拦wx、4=拦r、5=拦rx、6=拦rw、7=全拦。所以umask 077= 属主不拦,属组和其他全拦,结果是文件600、目录700。
严格说,「全权限减 umask」不是十进制减法,而是按位运算(& ~umask)。差别出现在 umask 里有奇数位时:
$ umask 003 # 拦掉其他的 wx $ touch f.txt # 减法直觉: 666 - 003 = 663? 错! # 实际: 666 & ~003 = rw-rw-r-- (644)
为什么不是 663?因为 3 = 011(拦 wx),但文件的全权限 666 里其他位本来就只有 rw-,没有 x 可拦。所以拦掉 wx 实际只拦掉了 w,结果是 rw-rw-r--(644)。「减法」在 umask 含奇数位(1/3/5/7)时会误导,严格要用按位与。但日常 umask 多是偶数(022/002/077),减法够用。
$ umask 077 $ touch a.txt $ ls -l a.txt -rw-r--r-- ... # 怎么不是 600?
如果改了 umask 还不生效,检查:
alias touch 或函数拦截?install -m 644)覆盖了 umask?umask 设置不持久$ umask 077 # 当前 shell 改了 $ exit # 退出 $ umask # 重开 shell, 又变回 022 022
umask 只对当前 shell(及其子进程)有效。要持久化,写进 ~/.bashrc 或 ~/.profile:
echo 'umask 077' >> ~/.bashrc
但改 /etc/profile 或 /etc/bash.bashrc 会影响所有用户,生产环境要慎重。
x 被忽略导致权限算错umask 022 → 目录 755 (有 x) umask 022 → 文件 644 (无 x)
记住文件和目录的全权限不同(目录 777、文件 666),所以同一个 umask 算出的结果不同。别把「文件的 644」错当成「目录的 644」(目录 644 是残废的,缺 x 进不去)。
umask 是「权限掩码」:新建文件/目录权限 = 全权限减去 umask。掩码拦的是权限,不是给权限。777(含 x)、文件 666(默认不给 x,出于安全)。umask 022 是最常见的默认:文件 666-022=644、目录 777-022=755。umask 三位对应 u/g/o,每位是要拦掉的权限和:0=不拦、2=拦 w、7=全拦。077 = 属组和其他全拦。& ~umask,但日常偶数 umask 用减法近似即可;奇数 umask 要小心借位错觉。umask 077 → 创建文件 → 恢复;持久化要写 ~/.bashrc。权限部分到此结束。下一节我们把视角抬到磁盘:df 看每个分区的总容量与使用率,du 看某目录下各项的占用。两者看似都在「看磁盘」,实则维度完全不同——一个是分区级,一个是目录级。还要破解一个经典谜题:「为什么我删了个 10G 大文件,磁盘空间没释放?」答案藏在进程持有的文件描述符里。