getfacl 命令详解与参数实测(Ubuntu 22.04)

以 Ubuntu 22.04(acl 2.3.1)为实测环境,逐参数验证 getfacl 的默认输出逐行解读(# 头、user/group/mask/other 条目语法、Removing leading 提示)、-a/-d/-c/-e/-E/-s/-n/-R/-L/-P/-p/-t 全部选项、符号链接跟随规则、错误退出码,并给出 mask 裁剪排障、递归审计与 ACL 备份清单的实战用法;全部输出为真实执行取证。

Linux命令Linux系统UbuntuUbuntu 22.04命令行用户权限2026/10/16

getfacl 命令详解与参数实测(Ubuntu 22.04)

实测目标:在 Ubuntu 22.04 服务器上逐个验证 getfacl 的全部选项,把它的默认输出逐行讲透(每一行都对应文件系统里的一条 ACL 记录),并给出"授权了却不生效"这类经典问题的定位方法。读类工具无副作用,全部命令真实执行取证。

一、环境信息

  • 操作系统:Ubuntu 22.04,x86_64
  • 命令所属软件包:acl 2.3.1-1(dpkg -l acl 实测;getfacl -v 输出 getfacl 2.3.1)
  • 文件系统:演示目录所在根文件系统已启用 POSIX ACL(本文全部 setfacl 授权与 getfacl 读回成功即为实证)
  • 测试数据:
    • 演示用户:aclu1(uid 1017,独立组 aclu1/gid 3106)、aclu2(uid 1018,gid 3107,同时是演示组 aclteam/gid 3108 的成员)
    • 演示目录:/root/demo/acl/,内含 acl-f1.txt(被授权对象)、acl-f2.txt(640 基线文件)、dir1/gdir(目录与符号链接演示用)
    • 演示用户准备命令与实测回显:useradd -m aclu1、useradd -m aclu2 后 id 输出 uid=1017(aclu1) gid=3106(aclu1) groups=3106(aclu1)、uid=1018(aclu2) gid=3107(aclu2) groups=3107(aclu2)
    • 制造扩展 ACL:setfacl -m u:aclu1:rw- /root/demo/acl/acl-f1.txt(setfacl 全参数详解见本专栏《setfacl 命令详解与参数实测(Ubuntu 22.04)》篇,本文引用处均给全命令,可独立执行)
  • 执行身份:root(getfacl 读 ACL 对文件有 r 权限即可,root 无限制)

二、命令概览

2.1 语法与测试数据

Usage: getfacl [-aceEsRLPtpndvh] file ...

getfacl 把文件的 ACL 以文本形式读出,输出格式与 setfacl/setfacl --restore 的输入格式完全同构——这使它既是"查看器",也是 ACL 的备份/迁移载体(4.3 节)。选项分三类:显示内容筛选(-a/-d/-c/-e/-E/-s/-n/-t)、遍历方式(-R/-L/-P/--one-file-system)、路径形态(-p)。

💡 技术拓展:POSIX ACL(本文对象)分访问 ACL(决定"谁能干什么",所有文件都有)与默认 ACL(只存在于目录,规定"以后在这里新建的对象继承什么 ACL")。每条记录叫一个条目,格式 <tag>:<qualifier>:<perms>,tag 有 user/group/mask/other 四种基础型加 default: 前缀变体。chmod 的 rwx 三段是 ACL 的"压缩视图",两套模型同一存储,互相同步(FAQ Q5)。

2.2 --help 全量输出

getfacl --help
getfacl 2.3.1 -- get file access control lists
Usage: getfacl [-aceEsRLPtpndvh] file ...
  -a, --access            display the file access control list only
  -d, --default           display the default access control list only
  -c, --omit-header       do not display the comment header
  -e, --all-effective     print all effective rights
  -E, --no-effective      print no effective rights
  -s, --skip-base         skip files that only have the base entries
  -R, --recursive         recurse into subdirectories
  -L, --logical           logical walk, follow symbolic links
  -P, --physical          physical walk, do not follow symbolic links
  -t, --tabular           use tabular output format
  -n, --numeric           print numeric user/group identifiers
      --one-file-system   skip files on different filesystems
  -p, --absolute-names    don't strip leading '/' in pathnames
  -v, --version           print version and exit
  -h, --help              this help text

注意 -e/-E 是一对互斥开关(显示/不显示生效权限注释),-L/-P 是一对遍历语义开关(跟随/不跟随符号链接)。

2.3 版本信息

getfacl -v
dpkg -l acl | tail -1
getfacl 2.3.1

ii  acl    2.3.1-1    amd64    access control list - utilities

三、参数逐项实测

3.1 默认输出:逐行解读(本文核心)

setfacl -m u:aclu1:rw- /root/demo/acl/acl-f1.txt
getfacl /root/demo/acl/acl-f1.txt
getfacl: Removing leading '/' from absolute path names
# file: root/demo/acl/acl-f1.txt
# owner: root
# group: root
user::rw-
user:aclu1:rw-
group::r--
mask::rw-
other::r--

逐行拆解(每一行都值得认识):

行含义
getfacl: Removing leading '/' ...提示信息(stderr):输入的绝对路径在 # file: 里剥掉了开头的 /,为了与 setfacl --restore 的相对路径规则配合;不是错误,退出码仍为 0(3.10 节用 -p 可关掉)
# file: root/demo/acl/acl-f1.txt对象路径(无前导 /)
# owner: root / # group: root属主/属组(-n 时显示为数字 ID,3.5 节)
user::rw-属主条目(qualifier 为空),等价 chmod 的 u 位
user:aclu1:rw-命名用户条目:给 aclu1 的授权——这就是 ACL 存在的意义,突破了"一属主一组一其他"的三段限制
group::r--属组条目,等价 chmod 的 g 位
mask::rw-掩码:所有命名用户/命名组/属组条目的生效权限上限(3.6 节演示裁剪)
other::r--其他人条目,等价 chmod 的 o 位

条目语法统一为 tag:qualifier:perms:qualifier 为空 = 基础条目(user::/group::),有名字 = 命名条目(user:aclu1:)。目录的默认输出结构相同,只是基础权限是 rwx 形态:

mkdir -p /root/demo/acl/gdir
getfacl /root/demo/acl/gdir
getfacl: Removing leading '/' from absolute path names
# file: root/demo/acl/gdir
# owner: root
# group: root
user::rwx
group::r-x
other::r-x

一个没有扩展 ACL 的目录也输出这三条基础条目——ACL 与传统权限是同一份数据的两种视图,所以 getfacl 对任何文件都有输出。

3.2 -c / --omit-header:去掉 # 头部

getfacl -c /root/demo/acl/acl-f1.txt
user::rw-
user:aclu1:rw-
group::r--
mask::rw-
other::r--

只剩条目本体,喂给脚本逐行处理时最干净。注意 Removing leading '/' 提示仍会打到 stderr(除非加 -p)。

3.3 -a / --access:只显示访问 ACL

getfacl -a /root/demo/acl/acl-f1.txt
user::rw-
user:aclu1:rw-
group::r--
mask::rw-
other::r--

文件只有访问 ACL,因此 -a 的输出与默认相同;差异要在目录上才看得出来(对照 3.4 节)。

3.4 -d / --default:默认 ACL(未设置与已设置)

目录未设置默认 ACL 时,-d 只输出头部、没有任何条目:

getfacl -d /root/demo/acl/gdir
# file: root/demo/acl/gdir
# owner: root
# group: root

(退出码 0,不是报错。)给目录设置默认 ACL 后再看:

setfacl -d -m u:aclu1:rwx /root/demo/acl/gdir
getfacl -d /root/demo/acl/gdir
getfacl /root/demo/acl/gdir
user::rwx
user:aclu1:rwx
group::r-x
mask::rwx
other::r-x

user::rwx
user:aclu1:r-x
group::r-x
mask::r-x
other::r-x
default:user::rwx
default:user:aclu1:rwx
default:group::r-x
default:mask::rwx
default:other::r-x
  • -d 只显示 default: 前缀的条目(该目录上实际存在的访问 ACL 是另一套);
  • 不带 -d 的完整输出把访问 ACL 与默认 ACL 一起列出:上半段五条是"目录自己"的访问 ACL,下半段五条 default: 是"以后新建对象"的继承模板。这是排查"继承不生效"时最该看的一屏。

3.5 -n / --numeric:数字 ID 输出

getfacl -n /root/demo/acl/acl-f1.txt
# owner: 0
# group: 0
user::rw-
user:1017:rw-
group::r--
mask::rw-
other::r--

aclu1 显示为 1017、root 显示为 0——名称解析被跳过。适用场景:用户/组在本地不存在的机器上核对(如拿到别的机器的备份清单)、或 NSS 解析缓慢的环境加速输出。

3.6 -e / --all-effective:显示生效权限注释(排障利器)

先收紧 mask 制造一次"授权被裁剪":

setfacl -m m::r-- /root/demo/acl/acl-f1.txt
getfacl -e /root/demo/acl/acl-f1.txt
user::rw-
user:aclu1:rw-	#effective:r--
group::r--	#effective:r--
mask::r--
other::r--

-e 给每个受 mask 约束的条目追加 #effective: 注释:aclu1 名义上 rw-,实际只有 r--。"给用户授权了却不生效"十有八九就是 mask 被收紧了,-e 一眼定位(修复方法见本专栏 setfacl 篇 3.6 节)。

3.7 -E / --no-effective:关闭生效注释

getfacl -E /root/demo/acl/acl-f1.txt
user::rw-
user:aclu1:rw-
group::r--
mask::r--
other::r--

同一份 ACL 不带 #effective: 注释。-e/-E 互斥,后写者生效;默认行为等于 -e(存在裁剪时自动显示注释)。

3.8 -s / --skip-base:跳过只有基础条目的文件

echo 'plain file' > /root/demo/acl/plain.txt
getfacl -s /root/demo/acl/acl-f1.txt /root/demo/acl/plain.txt
# file: root/demo/acl/acl-f1.txt
# owner: root
# group: root
user::rw-
user:aclu1:rw-	#effective:r--
group::r--
mask::r--
other::r--

两个文件传进去,只回显了有扩展 ACL 的 acl-f1.txt,plain.txt(仅基础条目)被跳过——批量找出"哪些文件设过 ACL"的唯一开关,退出码 0。

3.9 -R / --recursive:递归目录树

setfacl -R -m u:aclu1:rX /root/demo/acl/gdir
getfacl -R /root/demo/acl/gdir
# file: root/demo/acl/gdir
# owner: root
# group: root
user::rwx
user:aclu1:r-x
group::r-x
mask::r-x
other::r-x

# file: root/demo/acl/gdir/sub
# owner: root
# group: root
user::rwx
user:aclu1:r-x
group::r-x
mask::r-x
other::r-x

# file: root/demo/acl/gdir/sub/nested.txt
# owner: root
# group: root
user::rw-
user:aclu1:r--
group::r--
mask::r--
other::r--

-R 按目录树顺序逐个输出,每个对象一段(段间空行)。配合 -c 可只留条目、配合 -s 可只看有扩展 ACL 的对象(4.2 节实战组合)。遍历时符号链接默认被当作对象本身处理,跨文件系统行为由 --one-file-system 控制(--help 原文:skip files on different filesystems,挂载点场景使用)。

3.10 -p / --absolute-names:保留路径前导 /

getfacl -p /root/demo/acl/acl-f1.txt
# file: /root/demo/acl/acl-f1.txt
# owner: root
# group: root
user::rw-
user:aclu1:rw-	#effective:r--
group::r--
mask::r--
other::r--

# file: 里保留了完整的 /root/...,同时 Removing leading '/' 提示也不再出现。用 --restore 恢复时路径按 # file: 原样解释,因此在哪级目录执行、路径写成什么形态,备份与恢复两端必须对齐(setfacl 篇 3.15 节有完整闭环演示)。

3.11 -t / --tabular:表格输出

getfacl -t /root/demo/acl/acl-f1.txt
USER   root      rw-     
user   aclu1     rW-     
GROUP  root      r--     
mask             r--     
other            r--     

一行一个条目,人读更快。注意 rW- 的大写 W:表格输出里大写字母表示"该位被 mask 裁剪、实际不生效"(aclu1 条目 rw- 被 mask r-- 裁成 r--),小写表示实际生效——这是 -e 生效注释的表格版等价物。

3.12 符号链接:默认跟随、-P 不跟随、-L 显式跟随

ln -sf /root/demo/acl/acl-f2.txt /root/demo/acl/glink
getfacl /root/demo/acl/glink
getfacl -P /root/demo/acl/glink
getfacl -L /root/demo/acl/glink
# file: root/demo/acl/glink
# owner: root
# group: root
user::rw-
group::r--
other::---

(三条命令实测:默认与 -L 输出相同,均为目标文件 acl-f2.txt 的 ACL,头部路径仍是链接名;-P 输出为空、退出码 0。)

  • 默认与 -L:跟随链接读取目标文件的 ACL;
  • -P:严格不跟随,而符号链接自身不存储 ACL,所以输出为空但不报错;
  • 头部 # file: 恒为命令行里写的路径(glink),内容才是解析结果——核对时别被路径迷惑。

3.13 错误与退出码

getfacl /root/demo/acl/ghost.txt
getfacl: /root/demo/acl/ghost.txt: No such file or directory

不存在的对象报错、退出码 1;权限不足时报 Permission denied 同样退出码 1。Removing leading '/' 是提示不是错误(退出码 0,见 3.1 节)。批量场景 getfacl 会对每个对象独立报错,脚本判断整体成败应看退出码而非 stderr。

3.14 技术拓展:getfacl 与 ls -l 对比

对比项getfaclls -l
输出粒度逐条 ACL 条目(命名用户/组、mask、default 全展示)9 位压缩视图(属主/属组/其他)
扩展 ACL 迹象完整条目末尾一个 + 号(仅提示"有扩展 ACL")
mask 裁剪可见性-e 显示 #effective:(3.6 节)不可见
默认 ACL-d 完整展示不可见
可机读性条目即 setfacl 输入,可备份恢复(4.3 节)面向人
数字 ID-n 支持ls -n 支持

典型分工:ls -l 里的 + 负责"提醒有 ACL",真正的授权细节必须进 getfacl 看;两者配合才不会误判权限(4.1 节实战)。

四、实战示例

4.1 定位"授权了却写不进去":mask 裁剪排查

setfacl -m u:aclu1:rw- /root/demo/acl/acl-f1.txt
setfacl -m m::r-- /root/demo/acl/acl-f1.txt
ls -l /root/demo/acl/acl-f1.txt
getfacl -e /root/demo/acl/acl-f1.txt
echo '--- aclu1 尝试写入 ---'
su -s /bin/bash aclu1 -c 'echo x >> /root/demo/acl/acl-f1.txt'; echo "退出码=$?"
-rw-r--r--+ 1 root root 23 Oct 16 14:29 /root/demo/acl/acl-f1.txt
getfacl: Removing leading '/' from absolute path names
# file: root/demo/acl/acl-f1.txt
# owner: root
# group: root
user::rw-
user:aclu1:rw-	#effective:r--
group::r--	#effective:r--
mask::r--
other::r--

--- aclu1 尝试写入 ---
bash: line 1: /root/demo/acl/acl-f1.txt: Permission denied
退出码=1

复现一个高频排障场景:aclu1 被授了 rw- 却追加写入被拒(Permission denied,退出码 1)。定位链:ls 的 + 证明有扩展 ACL → getfacl -e 的 #effective:r-- 注释直接点名 → mask 是 r--,把命名用户条目裁剪到只读。处理:放宽 mask(setfacl -m m::rw-)或改用会自动重算 mask 的授权方式(setfacl 篇 3.6 节实测),修完再 getfacl -e 复核注释消失。

4.2 递归审计目录树:找出所有设过 ACL 的对象

getfacl -Rs -c /root/demo/acl/gdir
getfacl: Removing leading '/' from absolute path names
user::rwx
user:aclu1:r-x
group::r-x
mask::r-x
other::r-x

user::rw-
user:aclu1:r--
group::r--
mask::r--
other::r--

-R 递归 + -s 跳过纯基础对象 + -c 去头:gdir 树里共 3 个对象,此刻 gdir 本体只剩基础条目(getfacl -p /root/demo/acl/gdir 复核仅 user::/group::/other:: 三条),被 -s 过滤,输出只剩 gdir/sub 与 nested.txt 两段——每一段就是一个设过扩展 ACL 的对象。巡检脚本用它回答"这个树里谁被特殊授权了",比全量 dump 干净得多。

再补一组对照,确认 -s 的过滤粒度:

getfacl -Rs -c /root/demo/acl/acl-f2.txt
getfacl: Removing leading '/' from absolute path names
user::rw-
group::r--
group:aclteam:r-x
mask::r-x
other::---

acl-f2.txt 带 group:aclteam:r-x 扩展条目,同样完整输出——-s 的过滤标准是"只有基础条目",与对象类型(目录/文件)、扩展条目的种类都无关。

4.3 生成 ACL 备份清单:为恢复做准备

getfacl -R /root/demo/acl/gdir > /root/demo/acl/gdir-backup.acl
wc -l /root/demo/acl/gdir-backup.acl
head -13 /root/demo/acl/gdir-backup.acl
25 /root/demo/acl/gdir-backup.acl
# file: root/demo/acl/gdir
# owner: root
# group: root
user::rwx
group::r-x
other::r-x

# file: root/demo/acl/gdir/sub
# owner: root
# group: root
user::rwx
user:aclu1:r-x
group::r-x

输出重定向即清单落盘(stderr 的 Removing 提示不会混进文件)。这份清单配合 setfacl --restore=gdir-backup.acl 可在 ACL 被误清后整体还原,完整闭环(破坏→恢复→复核)见本专栏 setfacl 篇 3.15 节。迁移场景还能改主机后恢复——# file: 相对路径形态决定在哪个目录下执行恢复。

五、注意事项与常见问题

Q1:ls -l 末尾的 + 到底表示什么?什么时候会出现? 表示文件带扩展 ACL:至少有一条命名用户/命名组条目,或者目录带默认 ACL。mask 会被 chmod 联动(FAQ Q5),但仅有 mask 变化不产生 +。出现 + 就该用 getfacl 看细节,仅凭 ls 的三段位判断权限会漏掉命名条目。

Q2:mask 是谁改的?为什么我的授权被裁剪了? 三个来源:setfacl 默认在每次修改后把 mask 重算为所有受约束条目的并集(这就是为什么普通授权后 mask 自动变大);chmod g± 会直接改写 mask(chmod 的 g 位与 mask 是同一份数据);显式 setfacl -m m::权限 或 -n(不重算)会人为收紧/冻结。getfacl -e 看到某条目带 #effective: 注释就是被裁剪了,修复思路见 setfacl 篇 mask 章节。

Q3:getfacl 的输出能直接喂回 setfacl 吗? 能,这正是条目格式的设计目标:单文件用 setfacl --set-file=清单 目标(整份替换),目录树用 setfacl --restore=清单(按 # file: 逐个还原)。注意两端路径形态要一致:清单里的 # file: 若无前导 /(默认剥掉),--restore 就按执行时所在目录的相对路径解析(3.10 节)。

Q4:为什么 getfacl -P 对符号链接输出是空的,退出码却是 0? 符号链接本身不存储 ACL(内核不为其保存 ACL 数据),-P 严格不跟随链接,因此无事可输出——不跟随又无内容,空输出加退出码 0 是正确行为而非故障(3.12 节实测)。想看链接指向的文件,用默认形式或 -L。

Q5:ACL 和 chmod 是什么关系,会互相覆盖吗? 同一份存储的两个视图:user::/group::/other:: 三条基础条目就是 chmod 的三段位,chmod 改它们等于改 ACL;反过来 getfacl 看到的 group:: 在有扩展条目时语义上对应 mask(ls -l 的属组位显示的其实是 mask 值)。所以 setfacl 之后跑 chmod、或 chmod 之后看 getfacl,数值变化都是"同一份数据被另一个视图改写",不存在两套账。默认 ACL 属于目录的扩展数据,chmod 不触碰它。

六、参考链接