Linux 文件权限与所有权:chmod 到底在改什么
「chmod 777 一下就好了」是服务器上最常见的危险操作。理解了权限模型,你就知道该给什么、不该给什么。
一、rwx 是什么
ls -l index.html
# -rw-r--r-- 1 www-data www-data 3166 Sep 17 10:00 index.html
# ↑↑↑↑↑↑↑↑↑
# ││││││││└─ 其他用户 other:r--
# ││││││└── 同组 group:r--
# │││└──── 所有者 user:rw-
# └└─────── 文件类型:- 普通文件,d 目录,l 软链三组,每组三个字符:
| 分组 | 作用对象 |
|---|---|
| user (u) | 文件所有者 |
| group (g) | 所属用户组 |
| other (o) | 其他所有人 |
对文件:r 能读内容,w 能改内容,x 能当程序执行。
对目录:r 能列出里面有啥,w 能增删文件,x 能「进入」这个目录。
目录必须有
x。只有r没有x,你能看到文件名但打不开,会报 Permission denied —— 这是 403 的常见原因之一。
二、数字表示法
把 rwx 当成三位二进制:
| 权限 | 二进制 | 值 |
|---|---|---|
--- | 000 | 0 |
--x | 001 | 1 |
-w- | 010 | 2 |
-wx | 011 | 3 |
r-- | 100 | 4 |
r-x | 101 | 5 |
rw- | 110 | 6 |
rwx | 111 | 7 |
所以 chmod 644 file = 所有者 rw-、组 r--、其他 r--;chmod 755 dir = 所有者 rwx、其他 r-x。
常用组合:
| 模式 | 适用 |
|---|---|
| 644 | 普通文件(配置、网页) |
| 755 | 目录、可执行脚本 |
| 600 | 私钥、含密码的配置文件 |
| 700 | 私人脚本目录 |
| 777 | 永远不要用 |
三、chmod 与 chown
两个完全不同的东西:
chmod 修改「权限位」(rwx)
chown 修改「归谁所有」(user:group)
# 改权限
chmod 644 index.html
chmod u+x deploy.sh # 只给所有者加执行位
chmod -R 755 /var/www/baize # 递归改目录
# 改归属
sudo chown www-data:www-data /var/www/baize
sudo chown -R baize:baize /home/baize/.ssh
sudo chgrp www-data /var/www/baize # 只改组符号写法
u+x/g-w/o=r比数字更精确,不会误伤其他位。递归-R前先想清楚:目录要 755、文件要 644,一把chmod -R 755会让所有文件都变成可执行。
四、网站目录的标准配置
# 目录 755,文件 644,属主 www-data
find /var/www/baize -type d -exec chmod 755 {} \;
find /var/www/baize -type f -exec chmod 644 {} \;
sudo chown -R www-data:www-data /var/www/baize
# 需要写入的目录(上传、缓存)单独放宽
chmod 775 /var/www/baize/uploads五、umask:新建文件的默认权限
umask # 查看,常见 022
umask 0022 # 设置算法是「满权限减去 umask」:文件满权限 666、目录 777。
| umask | 新建文件 | 新建目录 |
|---|---|---|
| 022 | 644 | 755 |
| 002 | 664 | 775 |
| 077 | 600 | 700 |
写进 ~/.bashrc 只对当前用户生效;要全局生效写 /etc/profile。
六、三个特殊位
| 位 | 数字前缀 | 作用 |
|---|---|---|
| setuid | 4 | 执行时以所有者身份运行(如 passwd) |
| setgid | 2 | 目录下新建文件继承组;执行时以组身份运行 |
| sticky | 1 | 目录下只有文件所有者能删自己的文件(如 /tmp) |
chmod 2755 /srv/shared # setgid,协作目录常用
chmod 1777 /tmp # sticky
ls -ld /tmp # drwxrwxrwt 末尾的 t 就是 sticky
# 找出系统上所有 setuid 文件(安全审计会看)
find / -perm -4000 -type f 2>/dev/null七、排错:Permission denied 怎么查
# 逐级看路径上每一层的权限(这个命令很好用)
namei -l /var/www/baize/index.html
# 确认 nginx 以哪个用户跑
grep "^user" /etc/nginx/nginx.conf
ps aux | grep nginx | head -3
# 以目标用户身份测试能否读取
sudo -u www-data test -r /var/www/baize/index.html && echo OK || echo FAIL
# SELinux/AppArmor 也会挡(Debian 默认不开 SELinux)
getenforceACL(访问控制列表) 用于更细粒度的授权:
setfacl -m u:baize:rwx /srv/shared # 单独给某人权限
getfacl /srv/shared记住三条就够:文件 644、目录 755、密钥 600。剩下的都是这几条的变体。
