新手在服务器上最常见的三类报错——网页 403、脚本 Permission denied、SSH 密钥被拒——排查到最后十有八九落在同一个东西上:权限位。多数教程只会让你背「目录 755、文件 644、密钥 600」,背完还是不知道为什么。这篇把 rwx 的真实语义、数字的来历、umask 怎么决定新文件权限讲透,再补上误操作后的修复命令。做完这一次,以后不用再背。
先把 ls -l 第一列读对
ls -l /var/www
drwxr-xr-x 3 www-data www-data 4096 Oct 17 09:30 html
-rw-r--r-- 1 deploy deploy 512 Oct 17 09:12 index.html
第一列共 10 个字符,含义拆开看:
| 位置 | 示例 | 含义 |
|---|---|---|
| 第 1 位 | d | 文件类型:d 目录,- 普通文件,l 软链接 |
| 第 2-4 位 | rwx | 属主(owner)权限 |
| 第 5-7 位 | r-x | 属组(group)权限 |
| 第 8-10 位 | r-x | 其他人(others)权限 |
r、w、x 对文件和对目录是两套语义,口诀背不通的根源在这里:
| 权限 | 对文件 | 对目录 |
|---|---|---|
r (4) | 读文件内容 | 列出目录里的文件名(ls) |
w (2) | 修改文件内容 | 在目录里新建、重命名、删除文件 |
x (1) | 执行该文件 | 进入该目录(cd)、访问其中的文件 |
注意目录的 w:删除一个文件只需要对所在目录有 w,文件本身只读照样能被删。想保护文件,光锁文件没用,得锁目录。
目录的 x 位:被忽略的通行证
目录的 x 位是整条路径的通行证——路径上任何一级目录缺 x,后面的文件权限再宽松也访问不到。四个状态对比如下,以属主视角为例:
| 目录权限 | ls 列目录 | 新建文件 | cd 进去 | 读已知名字的文件 |
|---|---|---|---|---|
rwx (7) | ✓ | ✓ | ✓ | ✓(还受文件自身权限限制) |
r-x (5) | ✓ | ✗ | ✓ | ✓ |
-wx (3) | ✗ | ✓ | ✓ | ✓ |
--x (1) | ✗ | ✗ | ✓ | ✓ |
排查「文件明明 644 却读不了」这类问题,用 namei -l 沿路径逐级查一遍,比逐层 ls -ld 快得多:
namei -l /var/www/html/index.html
f: /var/www/html/index.html
drwxr-xr-x root root /
drwxr-xr-x root root var
drwxr-xr-x root root www
drwxr-x--- root www-data html
-rw-r--r-- deploy deploy index.html
输出里 html 这一级是 drwxr-x---,属组 www-data 有 x。如果 Nginx 以 www-data 运行就能进;换成其他用户运行,即便文件本身 644,也会收到 403。问题出在路径上的目录,与文件无关。
数字法 755/644:算术代替背诵
三位数字从左到右对应属主、属组、其他人,每位是三种权限的和:r=4、w=2、x=1。
| 数字 | 权限 | 典型用途 |
|---|---|---|
7 | rwx | 目录;可执行脚本(属主) |
6 | rw- | 普通数据文件(属主) |
5 | r-x | 目录或脚本(属组/其他人) |
4 | r-- | 纯只读文件 |
0 | --- | 不给任何权限 |
于是「目录 755、文件 644」根本不用背:目录需要 x 才能进,所以是 7 和 5;普通文件不需要 x,所以是 6 和 4。反过来,chmod 755 index.html 给一个网页文件加上 x 位,属于典型误操作——多出来的 x 没有功能意义,还会让某些安全扫描工具报警。
查看某个文件当前权限的数字形式:
stat -c '%a %U:%G %n' /var/www/html/index.html
644 deploy:deploy /var/www/html/index.html
数字法一次设齐三位,适合恢复默认;只调整其中一位时,符号法更稳:chmod g+w file(给属组加写)、chmod o-rwx file(把其他人的权限全部拿掉)、chmod u=x file(属主只留执行)。= 会覆盖该角色的全部权限,漏写一个字母就是真丢权限,混合使用时留意。
umask:新文件权限出厂默认从哪来
新建文件的权限由 umask 决定。内核对普通文件的权限上限是 666、目录是 777,创建时减去 umask 位就是最终结果:
| 对象 | 上限 | 默认 umask | 实际结果 |
|---|---|---|---|
| 普通文件 | 666 | 022 | 644 |
| 目录 | 777 | 022 | 755 |
Ubuntu 24.04 默认 umask 是 022(配置在 /etc/login.defs 的 UMASK 项),所以新建文件天然 644、目录天然 755。验证方法:
umask
touch /tmp/umask-test && mkdir /tmp/umask-dir
stat -c '%a %n' /tmp/umask-test /tmp/umask-dir
0022
644 /tmp/umask-test
755 /tmp/umask-dir
想让某个用户创建的文件默认不给其他人读(比如放敏感数据),把 umask 027 写进该用户的 ~/.profile,重新登录生效。两点提醒:umask 只影响之后新建的文件,已有文件不动;目录上限 777 减 umask 后总保留 x,文件上限 666 里没有 x,这就是脚本新建后永远要手动 chmod +x 的原因。
chown:改归属比改权限更快
很多时候权限位没错,错的是归属。典型场景:用 root 把数据拷到新目录,目录归 root,业务用户写不进去。改一次归属,比重排一堆权限位省事:
sudo chown deploy:deploy /data/app
sudo chown -R www-data:www-data /var/www/html
冒号后是属组,-R 递归整棵目录树。两个容易踩的细节:
- chown 会清掉 setuid/setgid 位。对设置了特殊位的文件改归属后,记得核对。
- 普通用户不能把文件「送」给别人。
chown改成别人需要 root;用户之间传文件,先挪到共享目录再改组。
配套的 chgrp 只改属组,chown :www-data file 等价。
chmod -R 777 为什么是灾难,以及怎么修回去
sudo chmod -R 777 /某目录 是网上答案区的高频毒方:所有用户可写可执行,等价于对全系统开放篡改权,而且 x 位泼到每个普通文件上。更危险的是 chmod -R 作用到 ~——~/.ssh 和里面的密钥一旦变成 777,sshd 判定权限过宽,密钥登录直接被拒。加固基线见服务器安全加固,密钥文件该是什么权限见 SSH 密钥认证。
已经误操作的,按类型分别修回。目录和文件的目标权限不同,不能用同一条命令一锅端,用 find 分开处理:
sudo find /var/www/html -type d -exec chmod 755 {} +
sudo find /var/www/html -type f -exec chmod 644 {} +
~/.ssh 被误改的修复:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
改完用 ssh -v user@host 重连,日志里 Permissions 0777 for ... are too open 的报错消失即恢复。
特殊权限位:setuid、setgid、sticky
三位数字之外还有第四位,管三件特殊事,写法是四位数字的首位:
| 位 | 数值 | 作用 | 现成例子 |
|---|---|---|---|
| setuid | 4 | 执行者临时获得文件属主身份 | /usr/bin/passwd(普通用户改密码要写 /etc/shadow) |
| setgid | 2 | 目录下新建文件自动继承目录属组 | 团队共享目录常用 2770 |
| sticky | 1 | 目录下的文件只有属主能删 | /tmp 是 1777 |
ls -l /usr/bin/passwd /tmp
-rwsr-xr-x 1 root root 59976 Nov 23 2023 /usr/bin/passwd
drwxrwxrwt 15 root root 40960 Oct 17 10:02 /tmp
属主位的 s 是 setuid,其他位的 t 是 sticky。共享目录一条命令配齐:
sudo mkdir -p /srv/shared
sudo chgrp deploy /srv/shared
sudo chmod 2770 /srv/shared
setgid 让组内新文件自动归 deploy 组,2770 又挡住组外的人。多用户协作目录照这个模板配即可。另外,chattr +i 能给文件加不可修改位,连 root 都改不了,适合锁定关键配置,lsattr 查看、chattr -i 解除。
常见问题(FAQ)
为什么文件是 644,Nginx 还是 403?
按 namei -l 沿路径查。九成是路径上某一层目录缺 x,或 Nginx 运行身份(www-data)不在目录的属组里。
chmod -R 777 之后再改回来,有没有安全残留? 权限位本身能修回,但暴露期间写入的文件、被篡改的内容无法靠 chmod 恢复。暴露窗口长的按入侵处理,查登录记录和异常文件。
umask 000 是什么意思? 新建文件直接拿满上限:文件 666、目录 777。等于把默认防线拆掉,服务器账号别这么配。
为什么我改了 umask,已有文件的权限没变?
umask 只在文件被创建那一刻起作用。已有文件用 chmod 逐个或批量改。
chown 之后服务还是读不了文件?
先确认服务进程的真实运行用户(ps -o user= -p <pid>),再检查该用户对整条路径的 x。还读不了就看 ACL:getfacl file。
最小可行清单:只记 4 件事
- 目录 755、文件 644、私钥 600——数字由
r=4, w=2, x=1加出来,推导优先于背诵。 - 排查 403 先跑
namei -l——问题多半在路径上某层目录,与目标文件无关。 - 拒绝一切
-R 777——批量修复用find分开处理目录(755)和文件(644)。 - 共享目录用
2770+ setgid——新文件自动继承属组,权限管理交给目录而不是每个文件。