传统权限的尴尬场景
"把这个项目目录分给老王看,但不能让他改代码。"
传统权限(ugo, user-group-other,用户-组-其他人模型)只有三组:文件所有者、所属组、其他人。如果老王不是这个组的人,只能给"其他人"开放权限。但这样每个人都能读,不安全。
我在一家外包公司时就遇到过这事。一个项目要对外包开放 read-only(只读权限),对内开放 write(写权限)。用传统权限做不到。当时查到了 ACL(Access Control List,访问控制列表),解决了问题。
ACL 是什么
ACL 就是给一个文件或目录挂一张"额外权限表"。这张表里可以针对某个特定用户、某个特定组单独设置权限,不受 ugo 模型的限制。
Linux 内核从 2.6 开始原生支持 ACL(ext2/3/4、XFS、Btrfs 都支持)。检查你的文件系统是否支持 ACL:
# 查看文件系统挂载选项,看有没有 acl 标志
mount | grep acl
# 如果没有显示 acl,可以手动挂载(ext4默认开启)
sudo mount -o remount,acl /home
现在绝大多数发行版默认就开启了,不用额外配置。
getfacl:查看ACL权限
getfacl(get file access control list,获取文件访问控制列表)看看文件上绑了哪些额外权限。
# 查看文件的ACL
getfacl /etc/passwd
# 查看目录的ACL
getfacl /var/www/html/
# 递归查看所有ACL(生产环境慎用,输出可能很长)
getfacl -R /var/www/html/
输出示例:
# file: /var/www/html/
# owner: www-data
# group: www-data
user::rwx
user:alice:r-x
group::r-x
group:devs:rwx
mask::rwx
other::---
default:user::rwx
default:group::r-x
default:other::---
我来解释一下每一行:
- ·
user::rwx:文件所有者的权限(传统ugo的user位) - ·
user:alice:r-x:特定用户 alice 的单独权限,这是ACL的核心 - ·
group::r-x:文件所属组的权限 - ·
group:devs:rwx:特定组 devs 的额外权限 - ·
mask::rwx:权限掩码,决定 ACL 能生效的最大权限 - ·
other::---:其他人权限 - ·
default: 开头的行:继承给新建文件/目录的默认权限
setfacl:设置ACL
setfacl(set file access control list,设置文件访问控制列表)是写 ACL 的命令。
给特定用户授权
# 给用户 alice 添加对 /project 目录的读和执行权限
sudo setfacl -m u:alice:rx /project
# 给用户 bob 添加读写权限
sudo setfacl -m u:bob:rw /project
-m 是 modify(修改),u:用户名:权限 是用户ACL条目的格式。
给特定组授权
# 给 devs 组添加读写执行权限
sudo setfacl -m g:devs:rwx /project
# 给 qa 组添加读和执行权限
sudo setfacl -m g:qa:rx /project
设置权限掩码
# 设置 mask,限制 ACL 的最大权限
sudo setfacl -m m:rx /project
mask 很关键。如果你设了 mask 为 rx,那么就算 bob 的 ACE(Access Control Entry,访问控制条目)写了 rwx,实际也只有 rx 生效。这是 ACL 的安全门。
Default ACL:自动继承权限
这是 ACL 最实用的功能之一。设置 default ACL(默认访问控制列表)后,在这个目录下新建的文件和子目录会自动继承 ACL 规则。
# 给目录设置 default ACL
sudo setfacl -m d:u:alice:rx /project
# 同时设置普通ACL和default ACL
sudo setfacl -m u:alice:rx,d:u:alice:rx /project
d: 前缀就是 default(默认)。设置了 default ACL 后,Alice 在 /project 下新建的任何文件和目录,她都自动有 rx 权限。
实际案例:我们团队的共享目录用 default ACL 解决了"新人加组后已有文件权限不够"的问题。只要在目录上设好 default ACL,根本不用担心新文件的权限漏配。
删除ACL条目
# 删除用户 alice 的ACL条目
sudo setfacl -x u:alice /project
# 删除 devs 组的ACL条目
sudo setfacl -x g:devs /project
# 删除所有扩展ACL(回到传统ugo模式)
sudo setfacl -b /project
-x 是 remove(移除),-b 是 remove all(全部移除)。
实战:多用户共享项目目录
假设你是运维,需要搭建一个开发环境:
需求:三个开发者(alice、bob、carol)共享目录 /srv/project。alice 和 bob 能读写,carol 只能读。运维组(ops)有 root-like(类似root的)管理权限。
# 创建目录和用户
sudo mkdir -p /srv/project
sudo useradd alice
sudo useradd bob
sudo useradd carol
sudo groupadd ops
sudo usermod -aG ops alice
sudo usermod -aG ops bob
sudo usermod -aG ops carol
# 设置目录归属
sudo chown root:ops /srv/project
# 设置基本权限:owner和ops组有完整权限,其他人啥也没有
sudo chmod 770 /srv/project
# 用ACL给 alice 和 bob 读写执行权限(他们已经有了)
sudo setfacl -m u:alice:rwx /srv/project
sudo setfacl -m u:bob:rwx /srv/project
# 给 carol 只读权限
sudo setfacl -m u:carol:rx /srv/project
# 设置default ACL,以后新建的文件自动继承
sudo setfacl -m d:u:alice:rwx,d:u:bob:rwx,d:u:carol:rx /srv/project
# 查看最终结果
getfacl /srv/project
这套方案在公司跑了两年多,比让所有人都进同一个组灵活得多。而且迁移到新服务器时,可以用 getfacl 导出再 setfacl 恢复。
备份和恢复ACL
# 导出整个目录树的ACL到文件
getfacl -R /srv/project > acl_backup.txt
# 恢复ACL
setfacl --restore=acl_backup.txt
能用文本形式保存和恢复,是 ACL 的亮点之一。不像某些专有格式,ACL 备份出来就是纯文本,可以直接 grep 搜索。
安全提醒
ACL和chmod的交互关系。 当你用 chmod 修改权限时,会同时影响到 ACL 的 mask 位。典型问题:chmod 把 others 权限关了,看起来 ACL 也失效了,其实 ACL 条目还在,只是被 mask 挡住了。
# 先设 ACL
sudo setfacl -m u:bob:rwx /project
# 然后误操作
sudo chmod 750 /project
# 这时 bob 的 ACL 条目被 mask 限制到 rx
getfacl /project
# 输出显示 mask::r-x,bob的rwx被压缩到r-x
ACL 不支持跨文件系统复制。用 cp -p 或 rsync -a 复制带 ACL 的文件到其他分区,ACL 会丢失。
ACL 数量过多影响性能。 每个文件 ACL 条目建议不超过几十条。极端情况下几百上千条 ACL 会影响文件系统性能。
定期用 getfacl -R / | grep -E '^user:' | wc -l 检查 ACL 使用量,别让权限管理失控。
什么时候该用ACL
单个文件需要精确控制少数用户的权限时,ACL 是最直接的工具。涉及大量用户或复杂层级时,考虑用 LDAP(轻量级目录访问协议)+ 组策略替代。
ACL 不是万能的,但它是传统权限模型最实用的补充。下次遇到"给特定用户开绿色通道"的需求,不用绕弯子了。