|
|
Linux 系统里,权限是安全的基石。你在服务器上建了个文件,谁能读、谁能写、谁能执行——这些事情搞不清楚,轻则脚本跑不起来,重则数据被人随意篡改。这篇文章从基础的 rwx 权限讲起,一路聊到 SUID、SGID、Sticky Bit 这些"高级货",再把 umask 和 ACL 也捋一遍。读完之后,你对 Linux 权限体系会有一个完整、扎实的认知。
rwx 权限基础
Linux 中每个文件和目录都有三组权限,分别对应三类用户:
Owner(属主):文件的拥有者
Group(属组):文件所属用户组的成员
Others(其他人):既不是属主也不在属组中的所有用户
每组权限由三个标志位组成:
| 标志 | 含义 | 对文件的作用 | 对目录的作用 |
|------|------|-------------|-------------|
| r | 读 | 查看文件内容 | 列出目录下的文件名 |
| w | 写 | 修改文件内容 | 在目录中创建、删除文件 |
| x | 执行 | 以程序方式运行 | 进入(cd)该目录 |
用查看时,你会看到类似这样的字符串。第一个字符表示文件类型(普通文件、目录),后面每三个字符一组,分别是属主、属组、其他人的权限。
数字表示法
每个标志位对应一个数字:r=4,w=2,x=1。三个位加起来就是一组权限的数值。
- rwx = 4+2+1 = 7
- r-x = 4+0+1 = 5
- r-- = 4+0+0 = 4
- 所以 rwxr-xr-- 对应 754
复制代码
记住这个换算规则,后面用设置权限时会频繁用到。
chmod:修改权限
有两种用法——符号模式和数字模式。
数字模式,简单直接:
- # 属主可读写执行,属组可读执行,其他人只读
- chmod 754 myfile.sh
- # 所有人都能读写
- chmod 666 data.txt
复制代码
符号模式,更灵活,适合只改某一组权限的场景:
- # 给属主加上执行权限
- chmod u+x script.sh
- # 去掉其他人的写权限
- chmod o-w config.yml
- # 给属组设置为只读
- chmod g=r document.txt
- # 同时操作多组
- chmod u+x,g-w,o-r myfile
复制代码
加个参数可以递归修改目录下所有文件:
- chmod -R 755 /var/www/html
复制代码
坦白说,日常用数字模式的频率更高,因为三个数字一写,权限一目了然。
chown 和 chgrp:修改归属
权限决定"能做什么",归属决定"对谁生效"。
- # 修改属主
- chown alice myfile.txt
- # 同时修改属主和属组
- chown alice:developers myfile.txt
- # 只修改属组(两种写法)
- chgrp developers myfile.txt
- chown :developers myfile.txt
- # 递归修改整个目录
- chown -R www-data:www-data /var/www
复制代码
一个常见场景:你用 root 部署了 Web 应用的文件,但 Nginx 是以用户运行的。如果不用把文件归属改过来,Nginx 根本读不到文件,页面直接报 403。
特殊权限:SUID、SGID、Sticky Bit
基础的 rwx 能解决大部分问题,但有些场景需要更精细的控制。这就是特殊权限存在的意义。
SUID(Set User ID)
作用对象:可执行文件。
效果:无论谁执行这个文件,执行时都临时获得文件属主的权限。
最经典的例子是命令。普通用户修改密码时需要写,但这个文件只有 root 能写。程序设置了 SUID 位,所以普通用户执行它时,进程以 root 身份运行,就能完成密码修改。
- ls -l /usr/bin/passwd
- # -rwsr-xr-x 1 root root ... /usr/bin/passwd
- # ^-- 注意这里是 s 而不是 x
复制代码- # 设置 SUID
- chmod u+s myprogram
- chmod 4755 myprogram # 数字模式下,千位的 4 代表 SUID
复制代码
SUID 很强大,但也很危险。如果一个 root 拥有的脚本被设了 SUID 又有漏洞,攻击者可以借此拿到 root 权限。所以不要随便给文件加 SUID,定期用审计一下系统里有哪些 SUID 文件,是个好习惯。
SGID(Set Group ID)
对可执行文件:执行时临时获得文件属组的权限,原理和 SUID 类似。
对目录:这才是 SGID 更常用的场景。在设了 SGID 的目录下创建的新文件,会自动继承目录的属组,而不是创建者的默认属组。
想象一个团队共享目录:Alice 和 Bob 都属于组。如果目录没有 SGID,Alice 创建的文件属组是她的默认组(可能是),Bob 未必能访问。设了 SGID 之后,新文件的属组自动变成,协作就顺畅了。
- # 给目录设置 SGID
- chmod g+s /shared/project
- chmod 2775 /shared/project # 千位的 2 代表 SGID
复制代码
Sticky Bit
作用对象:目录。
效果:目录里的文件只有文件属主、目录属主或 root 才能删除,其他人即使对目录有写权限也删不了别人的文件。
目录就是典型——所有用户都能在里面创建文件,但你不能删我的,我也不能删你的。
- ls -ld /tmp
- # drwxrwxrwt ... /tmp
- # ^-- t 就是 Sticky Bit
- chmod +t /shared
- chmod 1777 /shared # 千位的 1 代表 Sticky Bit
复制代码
把三个特殊权限的数字总结一下:SUID=4,SGID=2,Sticky=1,加在普通三位数字前面作为第四位(千位)。就是 SUID + rwxr-xr-x。
umask:控制默认权限
你有没有想过,为什么新建文件默认是 644,新建目录默认是 755?这就是 umask 在起作用。
系统创建文件时,理论最大权限是 666(文件)和 777(目录)。umask 是一个"掩码",用来从最大权限中"减掉"某些位。
- umask
- # 0022(常见默认值)
- # 文件默认权限 = 666 - 022 = 644 (rw-r--r--)
- # 目录默认权限 = 777 - 022 = 755 (rwxr-xr-x)
复制代码
严格来说这不是简单的算术减法,而是按位取反再做与运算,但"用最大权限减去 umask"在大多数场景下结果一致,好记也好用。
- # 临时修改 umask
- umask 027
- # 新文件: 666 - 027 = 640 (rw-r-----)
- # 新目录: 777 - 027 = 750 (rwxr-x---)
- # 永久修改:写入 ~/.bashrc 或 /etc/profile
- echo "umask 027" >> ~/.bashrc
复制代码
对于服务器来说,把 umask 设为 027 比默认的 022 更安全——直接砍掉了其他人的所有权限。
ACL:更精细的权限控制
传统的属主/属组/其他人三级权限有个明显短板:只能给一个用户和一个组设权限。如果你想让 Alice 能读写、Bob 只能读、Charlie 完全没权限——靠基础权限做不到。
ACL(Access Control List,访问控制列表)就是为了解决这个问题。
- # 给用户 bob 设置只读权限
- setfacl -m u:bob:r-- project.doc
- # 给 devops 组设置读写权限
- setfacl -m g:devops:rw- deploy.sh
- # 查看 ACL
- getfacl project.doc
复制代码- # file: project.doc
- # owner: alice
- # group: staff
- user::rw-
- user:bob:r-- # Bob 的专属权限
- group::r--
- group:devops:rw- # devops 组的专属权限
- mask::rw-
- other::---
复制代码
几个要点:
mask 是 ACL 权限的上限。即使你给 Bob 设了 rwx,如果 mask 是 r--,Bob 实际只有读权限。用可以调整 mask。
默认 ACL 用参数设置,对目录下新创建的文件自动生效:
- setfacl -d -m g:devops:rw- /shared/project
复制代码
看到权限末尾有个号,说明该文件带有 ACL 规则。
用可以清除文件上所有的 ACL。
ACL 在多团队协作的服务器上特别有用,它弥补了传统权限模型"粒度太粗"的不足。不过如果能用组权限解决的问题,就别上 ACL,保持简单永远是好事。
总结
Linux 权限体系可以分成四个层次来理解:基础权限(rwx + 数字表示法)解决"谁能做什么"的问题;归属管理(chown/chgrp)决定权限对谁生效;特殊权限(SUID/SGID/Sticky Bit)处理那些基础权限搞不定的场景;umask 和 ACL 则分别控制默认行为和精细化授权。
掌握这四层,日常的权限管理基本不会再让你头疼。 |
|