4.2 > Linux 文件/目录权限管理【核心命令】
概览
在上一节中我们对 Linux 的文件和目录权限管理的理论知识方面进行了全方面的介绍,这一节将学习与之相关的核心命令,其他进阶的、与权限安全相关的命令将在下一节中加更。
本节目录
- 概览
- 本节命令预览
- 基础权限与属性(必学)
- 查看权限
- 修改权限
- 链接相关
- ACL 扩展权限控制
- 高级文件属性
- 附加
本节命令预览
基础权限与属性:ls
、stat
、file
、chmod
、chown
、chgrp
、umask
链接相关:ln
、readlink
ACL:getfacl
、setfacl
高级文件属性:lsattr
、chattr
、getfattr
、setfattr
附加命令:install
基础权限与属性(必学)
查看权限
ls:
ls [选项] [文件]
常用组合:
ls -l # 显示文件的详细信息
ls -lh # 文件大小显示为易读的单位
ls -la # 详细列出当前目录下所有文件,包括 . 和 ..( -A 列出除 . 及 .. 以外的任何项目)
ls -ld [xxx] # 查看目录本身的权限和属性,而不是其内容
ls -lt # 按照文件内容的最后修改时间倒序排序
ls --time=xxx # 按指定时间戳排序(atime, access, use,ctime, status,birth, creation)
ls -ltc # 按照文件 ctime (权限、所有者等状态最后更改时间)排序
ls -lr # 逆序排序
ls -lS # 按照文件大小从大到小排序
ls -R # 递归列出所有文件和子目录
冷门组合:
ls -n # 将所有者和所属组的名称替换为其对应的 UID 和 GID
ls --color=xxx # 按照颜色排序列出(always(默认),auto,never)
ls -F # 在文件名后附加指示符号(目录后加 /,可执行文件后加 *,符号链接后加 @ 等)
ls -B # 不列出任何以 ~ 字符结束的项目(既备份项目)
ls -i # 显示每个文件的索引编号(inode 号)
ls -X # 根据扩展名按字母顺序排序
ls -Z # 输出每个文件的所有安全上下文信息
stat:
主要作用是显示文件或文件系统的状态信息。它不会读取文件的内容,而是从文件系统的元数据中提取详细信息。
stat [选项] 文件
常用组合:
stat file1 # 默认输出 file1 文件的所有信息
stat -L link_a # 输出符号链接 link_a 指向目标文件的状态信息
stat -t file1 # 简洁模式输出,常用于脚本
stat -f file1 # 输出 file1 所在文件系统的状态,而非文件本身的状态
冷门组合:
stat --cached=xxx file1 # 用于网络文件系统(如 NFS),是否使用本地缓存的属性信息(always、never)
# always 可以快速查询,但会牺牲准确性
# never 可以保证准确性,但会增加查询延迟
stat 最强大的功能是使用 --format 或 --printf 配合格式化占位符来精确控制输出的内容和格式,下面是一些文件格式常用的占位符:
占位符 | 描述 | 占位符 | 描述 |
---|---|---|---|
%a | 八进制权限位 | %A | 可读形式显示的权限位和文件类型 |
%d | 十进制设备号 | %D | 十六进制设备号 |
%C | SELinux 安全上下文 | %i | 索引节点号 |
%F | 文件类型 | %h | 硬链接数 |
%u | 所有者的用户 ID | %U | 所有者的用户名 |
%g | 所有者的组 ID | %G | 所有者的组名 |
%N | 如果是符号链接,则指向原文件名 | %n | 文件名 |
%m | 挂载点 | %s | 总大小(以字节为单位) |
%w | 文件创建时间,若未知则返回,人类可读 | %W | 文件创建时间戳;如果未知则为 0 |
%x | 上次访问时间,人类可读 | %X | 上次访问时间戳 |
%y | 上次数据修改时间,人类可读 | %Y | 上次数据修改时间戳 |
%z | 上次状态更改时间,人类可读 | %Z | 上次状态更改时间戳 |
下面是一些常用的文件系统格式占位符:
占位符 | 描述 | 占位符 | 描述 |
---|---|---|---|
%a | 非超级用户可用的空闲块数 | %b | 总数据块数 |
%c | 总文件节点数 | %d | 空闲文件节点数 |
%f | 空闲块数 | %i | 十六进制文件系统 ID |
%l | 文件名的最大长度 | %n | 文件名 |
%s | 块大小 | %T | 方便用户阅读的文件系统类型 |
自定义格式组合:
# -c 指定格式,并在末尾添加了换行符
stat -c "%n %s bytes" file1 # 查看 file1 的文件名、文件大小(bytes 为自定义的字符串)# --printf 解析自定义的转义字符
stat --printf "size: %s\n perm: %A\n"stat -f -c "FS Type: %T" /home # 查询 /home 所在文件系统的类型
file:
检查文件的内容,或利用一个“魔术数字”(magic number)数据库来确定文件的类型。
file [选项...] [文件...]
常用组合:
file myfile.txt myfile2 # 什么都不加,查看多个文件类型
file -z myfile.tar.gz # 解压并查看内部文件的文件类型
file -f fileList.txt # 从 filelist 中读取文件名,并查看文件类型
file -L link_a # 跟随符号链接,查看原文件的文件类型,而不是链接本身
冷门组合:
file --mime-type index.html # 仅输出 MIME 类型,不包括 MIME 编码,如 html 的 MIME 为 text/html
file -b file1 # 简洁模式,不显示文件名,只显示类型,适用于脚本
file -m custom.mgc data.bin # 使用自定义魔术文件,使用用户提供的魔术数字文件来判断类型
file -C -m custom.mgc # 将指定的魔术文件编译成二进制格式,以加快后续的加载速度
魔术文件是 file 命令用来判断文件类型时所依赖的核心数据库。它本质上是一个包含特定格式规则的文本文件,这些规则定义了在文件中特定偏移量(位置)上应该查找什么样的字节序列(或数据模式),这些字节序列被称为魔术数字 。其具有一下的优势:
- 文件扩展名很容易被用户随意更改或错误命名。魔术文件检查的是文件的实际内容,因此更准确。
- 可以识别无扩展名文件,许多 Unix/Linux 系统中的文件(如可执行文件、设备文件、日志文件)并没有扩展名,魔术文件是识别它们类型的唯一方法。
- 可以区分同一种扩展名下但内部格式不同的文件(例如,不同的 .tar 归档类型)。
魔术文件是一个纯文本文件,每行代表一个规则,规则通常包含以下四个字段,它们之间用 制表符 分隔:
-
偏移量:从文件开头(0)开始,需要检查的字节位置。
-
类型:要读取的数据类型。
-
值:要匹配的具体值或模式。可以是十进制、八进制 (0o…)、十六进制 (0x…) 数字,或者一个字符串。
-
描述:如果匹配成功,file 命令将输出的描述信息。
数据类型有如下这些(常用的):
类型 描述 用途 byte 1字节 检查文件头中的标志位或版本号的最低有效字节 short 2字节 检查文件头中的文件格式 ID 或数量计数器 long 4字节 检查文件头中的文件大小、偏移量或 CRC 校验和 quad 8字节 处理大型文件格式中的 64 位指针或大小 float 4字节 检查科学数据或图形文件中的浮点值 double 8字节 检查高精度的浮点数值 string - 任意长度的字节序列。在匹配时,可以指定一个字符串值 regex - 正则表达式,用于在文件内容中查找复杂的文本模式,通常用于区分不同类型的文本文件 date 4字节 Unix 时间戳,检查文件头中的创建或修改时间字段 qdate 8字节 用于 64 位系统中的时间戳 use - 引用另一个魔术文件或当前魔术文件的具名块 name - 定义一个具名块,用于为 use 类型提供一个可引用的目标 规则示例:
# 偏移量 类型 值 描述 # 0 string aaa 匹配到了 aaa# 在文件开始处(偏移量 0)查找字符串 aaa。如果找到,则报告类型为 匹配到了 aaa
复杂规则示例:
-
间接规则:允许 file 命令像读取指针一样工作,从而能够解析那些结构不固定、但文件头包含指向数据块的偏移量的文件格式。
偏移量(符号定义:&) 类型 值 描述 &5 lang 0xABCDE 描述 读取偏移量 5 处的整数并解析(读取指针) ➡️ 将解析的值作为新的实际偏移量并跳转(根据指针跳转) ➡️ 在新的偏移量上检查是否匹配值 0xABCDE(检查目标值) ➡️ 输出描述(即指针值)
-
相对偏移规则:当前规则的偏移量是基于前一条规则成功匹配的末尾位置。
规则号 偏移量(符号定义:>) 类型 值 描述 规则1 0 string hello 描述1 规则2 >6 short 2 描述2 从规则 1 匹配结束后 再往后数 6 个字节开始匹配 ➡️ 读取一个 short 整数 ➡️ 如果该整数是 2,则输出描述
-
逻辑、位操作:使用逻辑运算符(&, |, ^)或比较运算符(>, <, =, !)来对读取的值进行处理或条件判断。
规则号 偏移量 类型 值 描述 规则1 20 long &123 描述1 规则2 >>0 byte >0 描述2 规则3 10 byte >100 描述3 规则1:将偏移量位置的值同 123 做 AND 运算
规则2:进一步对上一个操作(规则1)的结果进行检查。如果结果大于 0(真),则输出描述
规则3:在偏移量 4 处读取一个 byte 字节,判断其值是否大于 100 -
特殊类型:也支持一些非标准的数据类型,用于特定目的。
规则号 偏移量 类型 值 描述 规则1 0 date >0 描述1 规则2 100 regex ^hello 描述2 规则1:检查文件头中的日期/时间戳是否有效,有效这输出描述
规则2:检查偏移量 100 处的字符串是否以 hello 开头,是则输出描述
-
修改权限
chmod:
允许系统管理员和用户控制谁可以对文件做什么(读取、写入、执行)
chmod [选项]... 模式[,模式]... 文件...
chmod [选项]... 八进制模式 文件...
两种模式:
- 符号模式:使用字母和符号来增、减或设置权限。对 u(user),g(group),o(other),a(all) 利用
+
,-
,=
来操作三类用户的权限。 - 八进制模式:使用 三 或 四 位八进制数字来表示权限,每位数字是 r (4)、w (2)、x (1) 三个值的组合,若需设置特殊权限,则第一位表示特殊权限,后三位表示三元组权限。
# 基本权限
chmod a=rwx file3 # 修改 file3 的权限为所有人可读写执行,等价于 chmod 777 file3
chmod -R 755 folder/ # 递归修改,目录及其内部所有文件和子目录的权限都设置为 755(八进制模式:等价于u=rwx,g=rx,o=rx)
chmod -v g+x,g-w file1 # 输出处理文件 file1 的更改,即使没有做任何更改(符号模式:原来存在 r,g+x,g-w 就等价于 g=rw)
chmod -c 644 file2 # 输出处理文件 file2 的更改,只有更改发生时才输出信息
chmod -R --preserve-root 777 / # 防止破坏根目录:如果尝试对 / 目录进行递归操作,chmod 会报错并停止操作,这是非常重要的安全机制# 特殊权限
chmod 4755 file1 # 给 file1 添加特殊权限 SUID(4),任何用户执行此文件时,都会临时获得文件所有者权限
chmod u+s file1 # 符号模式chmod 2755 file2 # 给 file2 添加特殊权限 SGID(2),任何用户执行此文件时,都会临时获得文件所属组权限
chmod g+s file2
chmod 2755 floder/ # 给 floder/ 添加特殊权限,floder/ 下创建的文件和目录自动同 floder/ 属于同一组chmod 1755 floder2/ # 给 floder2/ 添加特殊权限 Sitcky Bit(1),只有文件所有者和目录所有者才可以删除或重命名其中文件
chmod o+t floder2/ # 或 a+t
umask:
设置文件权限的默认权限,它决定了新创建的文件和目录的起始权限。当一个新文件或目录被创建时,系统会使用此值来 屏蔽 部分权限。
umask [-p] [-S] [模式]
umask # 以八进制模式输出屏蔽的权限
umask -S # 以符号模式输出屏蔽的权限
umask -p # 输出一个可直接执行的命令,确保将此值设置回 shell 环境
⚠️ 注意事项:
- 当 umask 命令输出四位数字时(如 0022),第一位数字代表默认屏蔽的特殊权限。
- 即使特殊权限位设置为 0(不屏蔽),新创建的文件或目录通常也不会自动拥有 SetUID 或 SetGID 权限,因为这些特殊权限一般只通过 chmod 命令手动设置。
- SetGID 对于目录有一个重要的默认行为:如果 umask 的第一位设置为 2 或更高,那么在新创建的目录上,系统可能会默认设置 SetGID 权限(具体行为取决于不同的系统发行版)。但在绝大多数情况下,第一位保持 0 是标准的做法。
你一定也观察到了一个现象:在四位模式下,第一位无论什么权限(0,1,2,4),新建的文件和目录都不会因为 umask 的屏蔽而获得特殊权限,这是为什么呢?
- 文件或目录最终获的最后权限遵循的逻辑是:
P权限=P主动权限&&按位取反(umask)P_{权限} = P_{主动权限} \,\,\,\,\, \&\& \,\,\,\,\, 按位取反(umask)P权限=P主动权限&&按位取反(umask)
其中:
主动权限 P:是程序在调用 open() 或 mkdir() 等系统函数创建文件目录时主动请求的权限
按位取反(umask):umask 值的按位取反(即屏蔽位的反面,表示允许的权限)
这就是为什么您感觉 umask 的特殊权限屏蔽位没有效果 —— 因为在用户空间下绝大多数程序默认不会请求特殊权限(即便请求了,内核为了安全起见,也会将此权限清除掉),所以 umask 也就屏蔽了个寂寞。那么非零特殊 umask 的意义何在?
- 其实,umask 2xxx 或 4xxx 的意义在于防御系统配置,它不是用来阻止用户请求的,而是用来阻止操作系统在文件创建后(作为一种自动、隐式的行为)赋予特殊权限。
- 这也是对可能存在的SetGID 目录继承(针对目录)或非标准程序(针对可执行文件)行为的最后一道明确的安全屏障。
chown:
用于修改文件或目录的所有者、所属组。
chown [选项] [所有者][:[组]] 文件/目录
常用选项:
chown tom file1 # 仅更改所有者为 tom
chown :devops file1 # 仅更改所属组为 devops
chown tom:devops file1 # 同时更改所有者为 tom,同时更改所属组为 devops
chown tom: file1 # 更改所有者为 tom,组自动设为所有者的默认组(可能为 tom)
chown -R www:data /var/www/html # 递归更改目录及其所有子文件和子目录的所有权
chown -v tom file1 # 详细显示每个被更改的文件或目录的信息
针对符号链接的选项:
chown -h tom link_a # 更改符号链接本身的所有权,而不是它指向的目标# -H 选项仅在与 -R 结合使用时才有意义
chown -HR tom link_a/ # 跟随链接,并对链接目标目录及其所有内容进行递归更改# 递归遍历目录时遇到的符号链接,则不跟随链接,只更改链接本身的所有权# -P 选项仅在与 -R 结合使用时才有意义
chown -PR tom link_a/ # 不跟随链接,只更改符号链接文件本身的所有权# 如果想要更改目录内部的文件所有权(包含链接),不应该指定 /link_a,而应该直接指定 /a 目录# -L 选项仅在与 -R 结合使用时才著意义
chown -LR tom link_a/ # 跟随链接,更改链接目标的所有权,如果目标是目录,则递归进入目标# 递归遍历目录时遇到的符号链接,则跟随链接,更改链接目标的所有权,如果目标是目录,则继续递归进入目标
⚠️ 针对符号链接选项的注意事项:
-P 是最安全、最保守的递归模式。它保证了无论符号链接位于命令行上还是目录内部,操作都只会影响链接文件本身,而不会“跳出”当前的物理目录结构去修改链接所指向的目标文件或目录。
-L 是最彻底的递归模式。它保证了无论符号链接出现在哪里,命令都会“逻辑上”跟随链接到目标位置,并对目标文件或目标目录下的整个子树进行操作。
-H 选项使得 chown -R 在启动递归时,对命令行上指定的目标链接采用 -L (逻辑) 行为;而在遍历目录树时遇到内部链接,则采用默认的 -P (物理) 行为。
相信你也遇到了在使用上述选项时,目录内部的软链接的所有权并未发生任何变化,那是因为内核、文件系统它们默认保护或忽略了软链接的所有权变更,这算是一种安全和设计上的选择。那么为啥要这样做呢:
- 符号链接的所有权通常不需要检查。因为它们一般都是 777,检查也没啥用,反而还增加了系统开销。
- 某些文件系统不支持修改,比如网络文件系统 NFS 或者某些较旧的 Linux 内核和文件系统的实现,压根儿就没有实现对软链接进行 lchown() 的功能。
因此,在很多现代 Linux 发行版和文件系统配置中,即使作为 root 用户使用 -h、-P 或 -R -H 尝试更改目录内部符号链接的所有权,操作也经常失败或被静默忽略。 这不是一个 bug,而是一种默认的设计选择或系统限制。
chgrp:
用于更改文件或目录的所属用户组。
chgrp [选项] 用户组 文件
常用选项:
chgrp bob file1 # 更改 file1 的所属组为 bob
chgrp -R bob folder/ # 递归操作,/floder 下所有物理文件和目录的组都变为 bob
chgrp -c bob file1 # 仅报告实际发生更改的文件
chgrp -v bob file1 # 报告所有被处理的文件
chgrp --reference=/etc/passwd file1 # 将 file 的组更改为 /etc/passwd 所属的组
针对符号链接的选项:
chgrp -RP bob folder/ # 将目录中的文件和子目录所属组变为 bob
chgrp -RL bob link_floder # 跟随链接,将目录中的文件和子目录所属组变为 bob(软链接通常会失败或忽略)
chgrp -RH bob link_floder # 跟随链接,将目录中的文件和子目录所属组变为 bob(软链接通常会失败或忽略)
注意事项:针对符号链接的选项用法和
chown
的-HLP
一样。
链接相关
ln:
ln 用来创建文件或目录链接的工具,链接本质上是给一个文件或目录起另一个名字或提供另一个访问路径。其创建的的链接主要有两种类型:硬链接 和 符号链接,也称为软链接。
ln [选项] 目标 链接名
常用选项:
ln file1 link_file1 # 创建硬链接
ln -b file1 link_file1 # 将 file1 重命名为 link_file1~(默认备份后缀),然后创建新链接(可以 -S 指定后缀名)
ln -s file1 link_file1 # 创建符号链接
ln -r /temp/file1 link_file1 # 创建相对路径的创建链接,链接所指向的文件显示为相对路径(常与 -s 连用)
ln -f file1 link_file1 # 不询问,强制创建新的链接,覆盖原来的链接
ln -i file1 link_file1 # 交互式确认
ln -d folder/ link_folder/ # 创建一个指向目录的硬链接(可能因系统限制而失败)
ln -t /temp/link_file1 file1 # 在指定目录中创建链接
冷门选项:
ln -T floder/ link_floder # 强制将 folder/ 视为普通文件来创建链接(可能会报错或覆盖目录本身)
ln -L link_a link_b # 解引用,创建一个 link_a 所指向的文件的硬链接
ln -P link_a link_b # 不解引用,创建一个指向 link_a 本身的硬链接
readlink:
显示符号链接所指向的路径;递归地解析路径中的所有符号链接,并返回绝对的、最简化的实际路径。
readlink [选项] 文件
常用选项:
readlink link_file1 # 读取符号链接所指向的内容
readlink -f link_a # 递归的读取整个链路上的软链接,并显示最后所指向的目标文件(如果链路出现问题也不会报错)(最常用)
readlink -e link_a # 严格模式,必须整个链路完好才能正确解析
readlink -v link_a # 显示解析过程中的错误,此命令默认是不显示错误的(一般配合其他选项一起使用)
readlink -n link_a # 显示时不带换行符(一般用于脚本中)
ACL 扩展权限控制
getfacl:
该命令用于获取文件或目录的访问控制列表(ACL)
getfacl [选项] 文件
常用选项:
getfacl file1 # 显示文件 file1 的访问 ACL 和默认 ACL(如果有)以及注释头部信息
getfacl -c file1 # 不显示 ACL 输出的注释头部(如文件名、所有者、属组等),这在脚本中很有用
getfacl -t file1 # 使用表格形式输出 ACL 条目,而不是默认格式
getfacl -n file1 # 以数字(UID/GID)代替用户名和组名来显示
getfacl -R mydir # 递归地显示 mydir 目录及其所有子文件和子目录的 ACL
getfacl -L link_a # 查看符号链接时跟随链接(这是默认行为)
getfacl -P link_a # 不跟随符号链接
冷门选项:
getfacl -s mydir # 跳过那些仅有基本(传统)ACL 条目的文件。只显示有扩展 ACL设置的文件
getfacl -a mydir # 仅显示目录 mydir 的访问 ACL。忽略默认 ACL
getfacl -d mydir # 仅显示目录 mydir 的默认 ACL。忽略访问 ACL
setfacl:
用于设置、修改、删除文件和目录的 ACL。
setfacl [选项] { -m|-M|-x|-X ... } 文件
常用选项:
# -m 修改或添加条目
setfacl -m u:john:rwx file1 # 为用户 john 添加对 file1 的读、写、执行权限# -x 删除指定的 ACL 条目
setfacl -x u:john file1 # 移除用户 john 在 file1 上的 ACL 规则# -b 移除所有扩展 ACL 条目
setfacl -b file1 # 移除所有命名用户、命名组和 Mask 条目,文件权限退回到传统模式# -k 移除默认 ACL 条目(仅适用于目录)
setfacl -k folder/ # 移除 folder/ 上的默认 ACL 继承规则# -d 操作针对默认 ACL(仅适用于目录)
setfacl -d -m u:john:rwx folder/ # 设置目录 folder/ 的默认 ACL,将来在该目录中创建的新文件将继承用户 john 的读写执行权限
冷门选项:
# --set 替换模式,完全替代现有条目
setfacl --set u::rw,g::r,o::r,u:john:rwx file1 # 移除所有现有 ACL,并将文件的 ACL 替换为新的三项基本权限和用户 john 的权限# -M 从文件中读取 ACL 条目进行修改或添加
setfacl -M rules.acl file1 # 从 rules.acl 文件读取规则,修改 file1 的 ACL# -X 从文件中读取要删除的 ACL 条目
setfacl -X rule.acl file1 # 从 rules.acl 文件读取规则,移除 file1 的 ACL# --mask 重新计算有效权限
setfacl --mask file1 # 强制 setfacl 根据所有命名用户/组和所属组的权限,重新计算并设置 Mask 条目# -n 不重新计算有效权限
setfacl -n -m u:john:r file1 # 在修改 ACL 时,不更新 Mask 值。这会影响所有扩展权限的实际有效权限# -L -P -H 操作同 chown 的用法一样
当你使用 -M
、-X
、--set
时,需要自己编写 rule.acl
文件,来告诉命令需要做什么,下面是一个 .acl
文件的示例:
# 推荐都写全称(user、group、other、mask、default),因为在替换模式下,不允许出现简称,这样做可以保证兼容性# file: file1
# owner: root
# group: root
user::rw- # 必须使用 user::,可以 getfacl 查看完整模式是怎么写的
group::r--
other::---
user:john:rwx
group:devs:r-x
mask::rwx
注意事项:
- 在
X
和M
的修改模式下,.acl
文件可以不用写完整的 ACL 列表,只需要写增量部分即可,但推荐写完整。- 在
--set
替换模式下,必须保证.acl
的完整性,因为必须这样做才能保证权限维护的原子性,如果只写部分 ACL 列表,则系统不知道该如何处理,可能会导致文件丢失其核心权限数据。
高级文件属性
lsattr:
用来查看文件和目录扩展属性。这些属性决定了文件或目录的行为,例如:是否可以被删除、是否可以被修改、是否可以被压缩等。
注意:这些属性通常只在 ext2、ext3、ext4、XFS、Btrfs 等支持扩展属性的 Linux 文件系统上有效。
lsattr [选项] [文件]
常用选项:
lsattr file1 # 列出文件的属性
lsattr -R folder/ # 递归列出目录及其所有子内容的所有属性
lsattr -d folder/ # 将目录当作文件看待,只列出本身的属性
lsattr -a ./ # 列出当前目录下的所有文件的属性,包含隐藏文件
lsattr -v file1 # 显示文件版本号
输出格式解析:
----i----------- /temp/file1
| 属性标志 | 文件名 |
注意事项:
- 具体属性标志的含义,请参见 上一节 内容的隐藏属性部分。
- 版本号是文件系统(如 ext4)在文件创建时分配的一个整数。一些底层的文件系统工具可能会使用此编号来跟踪文件的历史或状态,而在网络文件系统中,此编号可以确保文件操作(特别是缓存)能够正确的区分新旧文件。
chattr:
修改 Linux 文件系统中的扩展属性。
chattr [选项] [-+=标志] 文件# +: 添加指定的属性标志
# -: 移除指定的属性标志
# =: 精确设置指定的属性标志(会清除所有其他属性,谨慎使用)
常用选项:
chattr +a file1 # 为文件 file1 添加 a 标志,表示为只能追加内容,禁止删除和修改
chattr -R +i folder/ # 递归地更改目录及其内容的属性,对 folder 本身及其所有子文件添加 i 标志,标识为不可更改
chattr -f =a file1 # 静默模式,如果文件不存在,也不报告错误
chatte -v 110 file1 # 设置文件的版本号,这通常用于 NFS 或备份系统跟踪
getfattr:
查看文件和目录的拓展属性,与 lsattr 专注于查看系统级的底层文件标志(如 i、a)不同,其专注于查看存储在不同 命名空间 中的、由用户或系统添加的灵活元数据。
getfattr [选项] 文件
常用选项:
# -n 查看指定名称的单个拓展属性
getfattr -n user.creator file1 # 查看 file1 的 user.creator 属性# -d 查看所有拓展属性
getfattr -d file1# -m 匹配指定模式的属性,常用于匹配命名空间
getfattr -d -m user.* file1 # 匹配所有以 user. 开头的属性# -R 递归查看目录及其内容的属性
getfattr -R -d /data/docs # 列出包含自己和所有子文件的所有拓展属性# -L 遵循符号链接
getfattr -d -L link_to_a # 显示目标文件的属性(默认)# -P 不遵循符号链接
getfattr -d -L link_to_a # 显示符号链接本身的属性(默认)# --all-n 显示所有的属性名称,但不显示其值
getfattr --all-n file1# --only-value 仅显示属性值,不显示名称和元数据(一般用于脚本中)
getfattr -n user.creator --only-values file1
setfattr:
设置、修改或删除文件和目录的扩展属性。
setfattr {-n 属性名} [-v 属性值] [选项] 文件
常用选项:
# -n 指定要操作的属性名称,名称必须包含命名空间前缀
# -v 指定属性的值,如果省略,则将属性值设为空
setfattr -n user.name -v "tom" file1 # 设置一个名为 user.name 的属性,值为 tom# -x 删除指定的扩展属性
setfattr -x user.tag.a file1 # 删除属性 user.tag.a# -h 不遵循符号链接
# 不使用 -h 选项则表示遵循符号链接,将属性设置到链接所指向的目标文件上
setfattr -h -n user.name -v "spike" link_a # 设置链接文件 link_a 本身的属性
注意事项:
- 只有文件的所有者或 root 用户才能在
user.
命名空间中设置属性。对于 system 和 security 命名空间,通常需要 root 权限。- 扩展属性依赖于文件系统支持(如 ext2/3/4、XFS、Btrfs 等),如果文件系统不支持,setfattr 将失败。
- 扩展属性的名称和值的大小受到文件系统的限制,通常不能超过几个 KB。
知识链接:
ACL 权限在 Linux 文件系统上,是以扩展属性的形式存储的,其被内核存储在两个特定的 system 命名空间属性中:
属性名称 存储内容 描述 system.posix_acl_access 文件的访问 ACL 存储了除默认权限之外的所有 ACL 条目(命名用户、命名组、Mask 等),用于在每次访问时进行权限检查 system.posix_acl_default 目录的默认 ACL 仅存储在目录上,存储了新创建的文件/子目录将继承的 ACL 规则 注意:你不能通过
setfattr
来设置这两个值,因为它们的值是序列化了的二进制数据,不是人类可读的,而且 system 命名空间下的属性通常是受限的,以防止非授权用户篡改系统的访问控制信息。(chattr
和lsattr
操作的是文件 inode 中的文件标志 (Flags),它们与setfattr
和getfattr
操作的 xattrs(键值对) 是两个不同的元数据集合)
附加
install:
install 是一个标准的 GNU Core Utilities 命令(非 apt, yum, dnf 或 pacman 中的 install),用于将文件或目录复制到指定的位置并设置其权限和所有者。
其通常在 Makefile 或其他构建和安装脚本中使用,因为它能在一个步骤中完成复制、设置权限和设置所有者的操作,确保文件被“正确安装”。
install [选项] 源文件 目录
常用选项:
# -m 设置权限;-o 设置所有者;-g 设置所属组
install -m 755 -o root -g root myapp /usr/local/bin/
# 将 myapp 复制到 /usr/local/bin/,权限设置为 755,所有者为 root,所属组为 root# -d 创建目录
install -d -m 700 -o tom /etc/myapp/conf.d
# 创建目录 /etc/myapp/conf.d,权限设置为 700 ,所有者设置为 tom# -p 保留源文件的访问和修改时间戳
install -p aaa.conf /etc/myapp/
# 将配置文件 aaa.conf 复制到 /etc/myapp/,并保留其原始的创建和修改时间# -s 剔除符号表(一般用于二进制文件中,调用 strip 工具剥离可执行文件中的调试符号表、重定位信息等)
install -m 755 -s myapp /usr/local/bin/
# 将 myapp 复制到 /usr/local/bin/,设置权限为 755,并剔除多余的符号表,减少文件体积
和 cp 命令的区别:
- 从专业的自动化和脚本编写角度来看,
install
命令在很多情况下更优秀,因为它能在一个步骤中完成cp
和chmod
和chown
的工作。- 相较于
cp
命令,install
可以强制设置权限、所有者、所属组,并创建目录,而cp
命令只是简单的继承。
尽管
cp
可以完成文件复制的工作,但在涉及 系统安装、权限标准化、构建脚本 的专业场景中,install
命令是无可替代的首选工具。它的设计目的就是为了确保文件在安装完成后处于正确的、可预期的状态。
如果你觉得文章存在问题,可通过 邮箱 联系我,指出错误位置,我会进行核实更正,感谢各位大佬们