W2:Linux 文件权限
上一篇把 30 个核心命令过了一遍,这一篇钻进新人最容易翻车的一个点——文件权限。
实习生第一周改 Nginx 配置发现「Permission denied」一脸懵,二周看见同事 chmod -R 777 /var/www 学着用,三周给某个目录设错权限把网站搞挂。权限不懂就动生产,是早晚要还的债。
这一篇把 user/group/other、chmod、chown、sudo、特殊位、umask 一次梳理清楚。
一、ls -l 输出每一段都在说啥
$ ls -l /var/log/nginx/access.log-rw-r--r-- 1 nginx adm 12345 Jun 25 14:23 access.log│└─┬─┘└┬┘└┬┘│ └─┬─┘ └┬┘ └─┬─┘ └───┬───┘ └────┬────┘│ │ │ │ │ │ │ │ │ ││ │ │ │ │ │ │ │ │ └─ 文件名│ │ │ │ │ │ │ │ └─ 修改时间│ │ │ │ │ │ │ └─ 文件大小(字节)│ │ │ │ │ │ └─ 所属组│ │ │ │ │ └─ 属主│ │ │ │ └─ 硬链接数│ │ │ └─ other 权限│ │ └─ group 权限│ └─ user(属主)权限└─ 文件类型:- 普通文件 / d 目录 / l 软链接 / c 字符设备 / b 块设备 / s socket
记住三件事:
- 三段权限:
rw- / r-- / r--,分别对应属主 / 属组 / 其他人 - 每段三位:分别是
r(读)/ w(写)/ x(执行),用 - 占位表示无此权限 - 第一个字符是类型
二、数字权限:把 rwx 当二进制看就秒懂
每一段 rwx 三位,每一位有 / 无对应 1/0,三位刚好是 0-7:
三段拼起来就是三位数字。最常见的几个:
755 = rwxr-xr-x # 目录默认 / 可执行脚本644 = rw-r--r-- # 普通文件默认600 = rw------- # 私钥、证书、密码文件(**只属主可读写**)700 = rwx------ # 私人脚本目录777 = rwxrwxrwx # 全开(**几乎永远不要这么设**)
文件和目录上的 x 含义完全不同
文件的 x:能不能执行(脚本 / 二进制)目录的 x:能不能进入这个目录(cd 进去 / 看里面的子文件)
这是新人最容易栽的一个坑:
# 给一个目录 644,看似没问题chmod 644 mydircd mydir # ❌ Permission deniedls mydir # ✅ 能列出文件名cat mydir/file # ❌ Permission denied(要 x 才能访问目录里的具体文件)
目录的 x 是「能不能用这个目录」的开关,没有 x 等于这个目录是个黑洞——能看到名字,进不去。
三、符号权限:增量修改用它最顺手
数字法是「整段重写」,符号法是「在原基础上加减」:
chmod u+x script.sh # 给属主加可执行chmod g-w file.txt # 收回属组的写权限chmod o=r file.txt # 把 other 权限设成只读(覆盖式)chmod a+r file.txt # all(u+g+o)都加读权限chmod u+x,g-w,o-rwx file # 多个一起改,逗号分隔chmod -R 755 mydir # **-R 递归改子目录**
何时用数字、何时用符号:
- 新建文件 / 一次性设全:用数字(
chmod 755 script.sh) - 已有文件加 / 减某个位:用符号(
chmod +x deploy.sh)
四、特殊权限位:setuid / setgid / sticky
除了 rwx,每段还有一个「特殊位」,分别叫 s、s、t,挂在 x 那一位上显示。
ls -l $(which passwd)# -rwsr-xr-x 1 root root 68208 ... /usr/bin/passwd# ↑# 属主 x 位变成 s,就是 setuid
setuid(4xxx):执行时临时变身属主
chmod 4755 myprog# rwsr-xr-x
最经典例子是 /usr/bin/passwd:普通用户改自己密码要写 /etc/shadow,但 shadow 只有 root 能写。setuid 让 passwd 执行时短暂以 root 身份跑。
安全风险:自己写的脚本千万别 setuid,shell 脚本的 setuid 在多数现代 Linux 已经被内核屏蔽,硬要绕的话等于开后门。
setgid(2xxx):用在目录上,新建文件自动继承组
chmod 2775 /shared# rwxrwsr-x# 任何用户在 /shared 下创建的文件,所属组都是 /shared 的组# 团队共享目录最常用
sticky(1xxx):用在目录上,只能删自己创建的文件
ls -ld /tmp# drwxrwxrwt 17 root root 12288 ... /tmp# ↑# other 的 x 位变成 t# 1777 意味着:所有人可读写执行,但 **只能删自己创建的东西**
/tmp 是 1777 的经典代表。如果不加 sticky,任何用户都能删别人在 /tmp 里的文件,那就是灾难现场。
特殊位速查表:
| | | |
|---|
| | rwsr-xr-x | |
| | rwxr-sr-x | |
| | rwxrwxrwt | |
五、umask:新建文件的默认权限怎么来的
新建文件默认是 644、新建目录默认是 755,这是怎么算的?
文件最大权限 666(不给 x) - umask = 实际权限目录最大权限 777 - umask = 实际权限默认 umask = 022文件:666 - 022 = 644目录:777 - 022 = 755
umask# 看当前 umask# 0022umask 027 # 改成更严格(属主全权、组只读、其他无权限)# 文件变 640、目录变 750
生产服务器推荐 027,避免 other 默认能读到敏感配置。改完写到 /etc/login.defs 或 /etc/profile 持久化。
六、用户与组:三张表的结构
Linux 用户信息存在三个文件里,新人必须看一遍每个字段什么意思:
/etc/passwd
$ cat /etc/passwd | head -2root:x:0:0:root:/root:/bin/bashnginx:x:101:101:nginx user,,,:/var/cache/nginx:/usr/sbin/nologin
冒号分隔的 7 段:
用户名 : 密码占位 : UID : GID : 描述 : 家目录 : 登录 shell
/usr/sbin/nologin 表示该用户不能 SSH 登录——所有系统服务账号都应该是 nologin。
/etc/shadow(密码哈希,root 只读)
$ sudo cat /etc/shadow | head -1root:$6$xyz...$abc...:19500:0:99999:7:::
用户名 : 加密密码 : 上次改密时间 : 最短间隔 : 最长有效期 : 提醒提前几天 : 失效宽限 : 账号失效日 : 保留
$6$ 开头是 SHA-512 哈希;! 或 * 表示账号被锁。
/etc/group
$ cat /etc/group | head -2root:x:0:sudo:x:27:user1,user2docker:x:998:user1
把人加进 sudo 组就能 sudo、加进 docker 组就能不加 sudo 跑 docker(这也是安全风险,docker 组等于 root)。
七、用户管理:useradd / usermod / userdel
# 新建用户(带家目录、默认 shell 是 bash)sudo useradd -m -s /bin/bash alicesudo passwd alice # 设密码# 加入额外组(**-a 不可省,不然会覆盖原有组**)sudo usermod -aG sudo,docker alice# 改 shellsudo usermod -s /usr/sbin/nologin servicebot# 锁定 / 解锁账号sudo usermod -L alice # 锁sudo usermod -U alice # 解# 删用户(**-r 才删家目录,不加只删账号**)sudo userdel -r alice
给新人开账号的完整序列(背下来):
USER=newbiesudo useradd -m -s /bin/bash $USERsudo passwd $USER# 给临时初始密码sudo passwd -e $USER# 强制下次登录改密sudo usermod -aG sudo,docker $USER# 加入需要的组# 设 SSH 公钥sudo -u $USERmkdir -p /home/$USER/.sshsudo -u $USERchmod 700 /home/$USER/.sshsudotee /home/$USER/.ssh/authorized_keys <<< "ssh-ed25519 AAAAC3Nz... newbie@laptop"sudochown$USER:$USER /home/$USER/.ssh/authorized_keyssudochmod 600 /home/$USER/.ssh/authorized_keys
注意 .ssh 必须 700、authorized_keys 必须 600,权限错一位 SSH 直接拒绝公钥认证,且不报具体原因(只看 sshd 日志才看得到 Authentication refused: bad ownership or modes)。
八、sudo:永远用 visudo 改配置
sudo 让普通用户按需以 root(或其他用户)身份跑命令,是 Linux 安全的核心。
配置文件
/etc/sudoers # 主配置/etc/sudoers.d/* # 分文件配置(推荐自定义放这里)
永远不要直接 vim /etc/sudoers。一旦语法写错,整个 sudo 会瘫痪,连 root 都进不去(除非你保留了 root 直接登录)。
正确姿势:
sudo visudo # 编辑主配置,保存时自动语法校验sudo visudo -f /etc/sudoers.d/devops # 编辑分文件
visudo 在保存时会跑 visudo -c 校验,发现错误会问「Q 退出、E 重编、R 强存」,永远选 E 不要选 R。
常用 sudoers 写法
# 用户 主机=(目标用户:目标组) 允许的命令alice ALL=(ALL:ALL) ALL # 全权alice ALL=(ALL) NOPASSWD: ALL # 全权 + 免密(**慎用**)%sudo ALL=(ALL:ALL) ALL # sudo 组所有成员全权# 限定命令(推荐生产用法)deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart nginx, \ /usr/bin/systemctl reload nginx# 拒绝某些命令(黑名单)alice ALL=(ALL) ALL, !/bin/su, !/usr/bin/passwd root
日常 sudo 技巧
sudo -l # 看自己能跑哪些命令(强烈建议每个 sudoer 都会这条)sudo -u nginx ls /var/log # 以 nginx 用户身份跑sudo -i # 切到 root 交互 shell(**会加载 root 环境**)sudo su - # 同上,但更老派sudo !! # 上一条命令前面加 sudo 重跑(神技)sudo -k # 立即作废 sudo 凭证缓存
sudo 默认会缓存 15 分钟,所以连续敲 sudo 不需要每次输密码。需要更严格的场景把 Defaults timestamp_timeout=0 加到 sudoers 强制每次都问。
九、chmod 777 /etc 翻车实录
某次实习生帮人调 PHP,遇到「目录权限不够」,他想都没想:
5 分钟后:
- SSH 登录开始报警告
bad ownership or modes - sudo 直接拒绝执行:
/etc/sudoers is mode 0777, should be 0440
为什么这么致命:
/etc/sudoers/etc/shadow/etc/ssh/sshd_config- cron 拒绝执行权限过宽的 crontab 文件
恢复路径只有:用救援盘 / live CD 进单用户模式,手动 chmod 把每个关键文件改回正确权限——一台机器恢复一两小时,几十台机器…就等着写复盘吧。
记住三条铁律:
- 永远不要
chmod 777——99% 的「权限不够」其实是属主 / 属组不对,应该 chown 不是 chmod 777 - 永远不要
chmod -R 到 /etc、/usr、/var - 改权限前先
getfacl 备份一下:getfacl -R /path > /tmp/perms.bak,万一翻车能 setfacl --restore
十、安全实践小结
进入一台新服务器,先把这几件事做了:
# 1. 不要用 root 日常操作,建自己的账号sudo useradd -m -s /bin/bash $USER && sudo passwd $USERsudo usermod -aG sudo$USER# 2. SSH 禁 root 直接登录(编辑 /etc/ssh/sshd_config)PermitRootLogin noPasswordAuthentication no # 禁密码,强制密钥(W15 详讲)sudo systemctl restart sshd# 3. sudo 配限定命令,不要无脑 NOPASSWD ALLsudo visudo -f /etc/sudoers.d/deploy# deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart myapp# 4. 重要文件权限收紧sudochmod 600 /etc/ssh/ssh_host_*_keysudochmod 644 /etc/ssh/ssh_host_*_key.pub
写在最后
- 数字权限就是二进制:rwx 三位拼成 0-7,背熟 644/755/600/700 四个常用值
- chown 改属主、chmod 改权限
- 目录的 x 是「能不能进」,没有 x 等于黑洞
- 改 sudoers 永远
sudo visudo chmod -R 777 是问题创造机,不是问题解决方案- 设错 SSH 公钥权限(
.ssh 必须 700、authorized_keys 必须 600)会让密钥认证默默失败,先检查权限再查公钥内容