适用场景
有时需要让另一位已有普通用户读取报告目录,却不希望修改文件所有者,也不希望向所有人开放权限。访问控制列表(Access Control List,ACL)可以为指定用户补充权限,适合处理这种细粒度授权。
本文以 Ubuntu 24.04、本地支持 POSIX ACL 的文件系统和 Bash 终端为范围,整理日期为 2026-10-20。所有操作先在新建实验目录完成。网络共享、容器映射和其他安全模块可能叠加限制,不能仅凭本机实验结果推断其行为。
原理:目录权限与文件权限不同
文件的读取权限决定能否读取内容,目录的读取权限用于列出名称,目录的执行权限用于进入和访问其中对象。给文件授予读取权限,却不给上级目录通过权限,仍然会遇到访问被拒绝。
ACL 中的指定用户条目还受到权限掩码约束。掩码是相关条目的有效权限上限,所以看到用户条目包含读取权限,不代表最终一定能读取。Ubuntu 的 ACL 手册解释了这种判定规则。
默认 ACL 写在目录上,影响以后在目录内新建的对象。它不会自动追溯修改已经存在的文件,而且程序创建对象时请求的权限仍会限制最终结果。因此,普通新建文件通常不会因为目录默认 ACL 包含执行权限就变成可执行文件。
准备工作
需要一个有 sudo 权限的操作身份,以及一个不同于当前用户、已经存在的普通用户作为读取方。不要选管理员或系统服务身份,也不要为了实验修改真实业务用户的组成员关系。
检查工具是否存在:
command -v getfacl
command -v setfacl
如果缺少工具,可通过 Ubuntu 官方软件源安装 acl 软件包。后面的 viewer 表示读取方的实际用户名,labdir 表示自动生成的实验目录,acl_backup 表示自动生成的权限备份文件。所有命令在同一个 Bash 窗口执行。
分步骤操作
第一步:确认读取方并创建目录
read -r -p '输入已有普通用户的用户名:' viewer
id "$viewer"
id -u
id -u "$viewer"
labdir=$(mktemp -d /var/tmp/acl-readonly.XXXXXX)
acl_backup=$(mktemp "$HOME/acl-before.XXXXXX")
printf '%s\n' "$labdir" "$acl_backup"
getfacl -p "$labdir" > "$acl_backup"
确认两次用户编号不同,读取方也不是编号为零的超级用户。身份查询失败时应停止,不要继续执行授权。
临时目录通常只允许创建者访问。这里选择系统临时目录作为父目录,避免用户主目录自身的限制干扰实验。备份保存在实验目录之外,并保留完整路径,便于之后恢复。有关输出格式和绝对路径选项,参见 getfacl 手册。
第二步:设置当前访问和新文件继承规则
setfacl -m "u:${viewer}:r-x" "$labdir"
setfacl -d -m "u::rwx,u:${viewer}:r-x,g::---,m::r-x,o::---" "$labdir"
getfacl -p "$labdir"
第一条允许读取方列目录并通过目录;第二条建立默认 ACL:所有者保留权限,指定读取方得到读取与通过权限,所属组和其他人没有额外权限。
注意输出中普通条目和以 default 开头的条目分别作用于当前目录和以后创建的对象。不要只检查其中一部分。具体参数和掩码自动计算规则见 setfacl 手册。
第三步:创建无敏感内容的样本
printf '%s\n' '这是一份只读授权实验文件。' > "$labdir/report.txt"
getfacl -p "$labdir/report.txt"
文件是在默认 ACL 设置后创建的。查看其指定用户权限和有效权限,预期读取方可以读,但没有写入权限。若把一个旧文件移动进来,其权限可能保留原状,不能把移动操作当成新建对象继承的验证。
第四步:用读取方身份验证
sudo -u "$viewer" -- ls -l "$labdir"
sudo -u "$viewer" -- cat "$labdir/report.txt"
sudo -u "$viewer" -- test -w "$labdir/report.txt"
printf '文件可写检查退出码:%s\n' "$?"
sudo -u "$viewer" -- test -w "$labdir"
printf '目录可写检查退出码:%s\n' "$?"
前两条应能够列出并读取样本。后两次可写检查预期返回一,表示不可写;零表示可写,需要重新排查。必须紧接着读取退出码,因为执行其他命令会覆盖它。
验证方法与常见错误
成功标准包含三个方面:读取方能够浏览目录并读取样本;不能写入样本;不能在目录中创建或删除文件。最后一点取决于目录写入权限,不能只检查文件权限。
如果管理员能够读取而普通用户失败,应先检查上级目录,再看 ACL 的有效权限注释。不要直接扩大权限掩码来碰运气,因为这可能让其他指定用户或组的既有条目同时生效。
如果默认 ACL 已设置,但旧文件仍无法读取,通常是因为默认规则只影响新建对象。对业务目录补齐已有权限需要单独制定范围,不能把本实验命令随意改成递归操作。程序主动创建仅所有者可读的文件时,也可能限制继承后的有效权限。
安全与回退
先恢复实验目录原来的权限:
setfacl --restore="$acl_backup"
getfacl -p "$labdir"
这份备份只包含最初的实验目录,不包含后来新建的样本文件。因此,恢复目录后,样本自身可能仍保留 ACL,但读取方应已无法通过实验目录访问它。需要保留整个业务目录树的恢复能力时,必须在修改前备份对应的完整对象范围。
确认实验结束后,先核对打印出的目录路径,再删除本教程创建的样本和空目录:
rm -- "$labdir/report.txt"
rmdir -- "$labdir"
如果目录不为空,停止并查看内容,不要扩大删除范围。权限备份可随维护记录保留,确认无需回退后再清理。
参考资料与转载说明
本文依据上述公开资料进行中文原创整理,不是逐句翻译,也不替代厂商手册。操作前请核对自己的版本、型号和备份。
评论一下?