跳转到内容

文件权限与 ACL

适用于 CentOS Stream 9 & 10 / AlmaLinux 9.x & 10.x / Rocky Linux 9.x & 10.x

Linux 文件权限是系统安全的基石。每个文件和目录都有一套权限规则,控制谁可以读取、写入和执行它们。当基本权限无法满足需求时,ACL(访问控制列表)可以提供更精细的控制。

  • 理解 rwx 权限模型
  • 使用 chmod 修改权限(符号模式和八进制模式)
  • 使用 chownchgrp 修改属主和属组
  • SUID、SGID 和 Sticky Bit 特殊权限
  • 使用 ACL 实现精细权限控制
  • 理解和配置 umask
  • 一台已安装 EL 9.x 的系统
  • 拥有 sudo 权限的用户账户
  • 了解用户和组管理的基本概念
查看文件权限详情
$ ls -l /etc/nginx/nginx.conf
-rw-r--r--. 1 root root 2488 Mar 24 10:00 /etc/nginx/nginx.conf

输出各部分含义:

-rw-r--r--. 1 root root 2488 Mar 24 10:00 nginx.conf
│├──┤├──┤├──┤ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ └─ 文件名
│ │ │ │ │ │ │ │ └─ 修改时间
│ │ │ │ │ │ │ └─ 文件大小
│ │ │ │ │ │ └─ 属组
│ │ │ │ │ └─ 属主
│ │ │ │ └─ 硬链接数
│ │ │ └─ 其他用户权限 (other)
│ │ └─ 属组权限 (group)
│ └─ 属主权限 (owner)
└─ 文件类型(- 普通文件,d 目录,l 符号链接)
权限字符对文件的含义对目录的含义
r读取文件内容列出目录内容
w修改文件内容在目录中创建/删除文件
执行x执行文件(脚本/程序)进入目录(cd)

符号模式使用 u(属主)、g(属组)、o(其他)、a(所有)配合 +(添加)、-(移除)、=(设置)来修改权限。

给属主添加执行权限
$ chmod u+x script.sh
移除其他用户的写权限
$ chmod o-w file.txt
给属组添加读写权限
$ chmod g+rw shared.doc
设置属主读写执行,属组和其他只读
$ chmod u=rwx,g=r,o=r script.sh
给所有用户添加执行权限
$ chmod a+x script.sh

每个权限位对应一个数值:

权限
r4
w2
x1
-0

将属主、属组、其他用户的权限值分别相加:

数字权限说明
7rwx读 + 写 + 执行
6rw-读 + 写
5r-x读 + 执行
4r--只读
3-wx写 + 执行
2-w-只写
1--x只执行
0---无权限
设置权限为 755(属主 rwx,属组 r-x,其他 r-x)
$ chmod 755 script.sh
设置权限为 644(属主 rw-,属组 r--,其他 r--)
$ chmod 644 config.conf
设置权限为 700(属主 rwx,其他人无权限)
$ chmod 700 private-dir/
递归修改目录及其内容的权限
$ chmod -R 755 /var/www/html/
目录设为 755,文件设为 644(推荐做法)
$ find /var/www/html/ -type d -exec chmod 755 {} +
$ find /var/www/html/ -type f -exec chmod 644 {} +
修改文件的属主
$ sudo chown webuser /var/www/html/index.html
同时修改属主和属组
$ sudo chown webuser:webgroup /var/www/html/index.html
递归修改目录的属主和属组
$ sudo chown -R webuser:webgroup /var/www/html/
修改文件的属组
$ sudo chgrp developers project-file.txt
递归修改目录的属组
$ sudo chgrp -R developers /opt/project/

除了基本的 rwx 权限,Linux 还有三个特殊权限位。

当可执行文件设置了 SUID 位后,任何用户执行该文件时,都会以文件属主的身份运行(而不是执行者自身)。

查看 SUID 的经典示例:passwd 命令
$ ls -l /usr/bin/passwd
-rwsr-xr-x. 1 root root 32648 ... /usr/bin/passwd

属主权限中的 s 就是 SUID 标志。普通用户执行 passwd 时,进程以 root 身份运行,因此能够修改 /etc/shadow

设置 SUID(八进制前缀 4)
$ sudo chmod u+s /path/to/program
$ sudo chmod 4755 /path/to/program
查找系统中所有设置了 SUID 的文件
$ sudo find / -perm -4000 -type f 2>/dev/null

对文件:执行时以文件属组身份运行。

对目录:在目录中创建的新文件/子目录会自动继承该目录的属组,而不是创建者的主组。这对于团队协作目录非常有用。

设置 SGID(八进制前缀 2)
$ sudo chmod g+s /opt/shared-project/
$ sudo chmod 2775 /opt/shared-project/
验证 SGID 效果
$ ls -ld /opt/shared-project/
drwxrwsr-x. 2 root developers 4096 ... /opt/shared-project/

属组权限中的 s 就是 SGID 标志。

对目录设置 Sticky Bit 后,目录中的文件只能被文件的属主或 root 删除,即使其他用户对目录有写权限。最典型的例子是 /tmp

查看 /tmp 的 Sticky Bit
$ ls -ld /tmp
drwxrwxrwt. 15 root root 4096 ... /tmp

其他用户权限中的 t 就是 Sticky Bit 标志。

设置 Sticky Bit(八进制前缀 1)
$ sudo chmod +t /opt/shared-uploads/
$ sudo chmod 1777 /opt/shared-uploads/
权限八进制符号对文件对目录
SUID4u+s以属主身份执行(无特殊效果)
SGID2g+s以属组身份执行新文件继承目录的属组
Sticky1+t(无特殊效果)只有属主能删除文件
  1. 创建共享目录

    创建目录
    $ sudo mkdir /opt/team-share
  2. 设置属主和属组

    设置为 developers 组所有
    $ sudo chown root:developers /opt/team-share
  3. 设置权限和 SGID

    设置 SGID 确保新文件继承组
    $ sudo chmod 2775 /opt/team-share
  4. 验证

    确认权限设置正确
    $ ls -ld /opt/team-share
    drwxrwsr-x. 2 root developers 4096 ... /opt/team-share

    现在,developers 组的任何成员在该目录下创建的文件都会自动属于 developers 组。

  5. 测试

    以 developers 组成员身份创建文件
    $ touch /opt/team-share/test.txt
    $ ls -l /opt/team-share/test.txt
    -rw-rw-r--. 1 zhangsan developers 0 ... test.txt

umask 决定了新创建文件和目录的默认权限。新文件的权限 = 基础权限 - umask 值。

  • 文件的基础权限:666(不含执行位)
  • 目录的基础权限:777
查看当前 umask
$ umask
0022
以符号形式查看
$ umask -S
u=rwx,g=rx,o=rx

umask 0022 的效果:

基础权限umask实际权限
文件666022644 (rw-r—r—)
目录777022755 (rwxr-xr-x)
临时修改 umask(仅当前会话)
$ umask 027

umask 027 的效果:

基础权限umask实际权限
文件666027640 (rw-r-----)
目录777027750 (rwxr-x---)
永久修改用户的 umask
$ echo "umask 027" >> ~/.bashrc

当基本的 owner/group/other 权限模型无法满足需求时,ACL 可以为特定的用户或组设置独立的权限。

查看文件的 ACL
$ getfacl /opt/team-share/config.txt

输出示例(无额外 ACL):

opt/team-share/config.txt
# owner: zhangsan
# group: developers
user::rw-
group::rw-
other::r--
给特定用户添加读写权限
$ sudo setfacl -m u:lisi:rw /opt/team-share/config.txt
给特定组添加只读权限
$ sudo setfacl -m g:qa:r /opt/team-share/config.txt
查看设置后的 ACL
$ getfacl /opt/team-share/config.txt

输出示例:

opt/team-share/config.txt
# owner: zhangsan
# group: developers
user::rw-
user:lisi:rw-
group::rw-
group:qa:r--
mask::rw-
other::r--
设置用户 ACL
$ sudo setfacl -m u:用户名:权限 文件路径
设置组 ACL
$ sudo setfacl -m g:组名:权限 文件路径
删除特定用户的 ACL
$ sudo setfacl -x u:lisi /opt/team-share/config.txt
删除特定组的 ACL
$ sudo setfacl -x g:qa /opt/team-share/config.txt
删除文件的所有 ACL
$ sudo setfacl -b /opt/team-share/config.txt
递归设置目录的 ACL
$ sudo setfacl -R -m u:lisi:rwx /opt/team-share/

默认 ACL 可以让目录中新创建的文件自动继承 ACL 规则:

设置默认 ACL
$ sudo setfacl -d -m u:lisi:rw /opt/team-share/
$ sudo setfacl -d -m g:qa:r /opt/team-share/
查看默认 ACL
$ getfacl /opt/team-share/

输出示例:

# file: opt/team-share/
# owner: root
# group: developers
# flags: -s-
user::rwx
group::rwx
other::r-x
default:user::rwx
default:user:lisi:rw-
default:group::rwx
default:group:qa:r--
default:mask::rwx
default:other::r-x

现在在该目录中创建的新文件会自动包含对 lisiqa 组的 ACL 规则。

mask 定义了 ACL 中用户和组能获得的最大权限。即使你设置了某个用户的权限为 rwx,如果 mask 是 r--,该用户实际有效权限也只有 r--

设置 mask
$ sudo setfacl -m m::rx /opt/team-share/config.txt

假设有以下需求:

  • 项目目录 /opt/webapp 属于 webdev
  • webdev 组的成员有完整读写权限
  • qa 组只能读取不能修改
  • 用户 deployer 有完整权限用于部署
  • 新创建的文件自动继承这些规则
  1. 创建目录和组

    创建目录和组
    $ sudo mkdir -p /opt/webapp
    $ sudo groupadd webdev
    $ sudo groupadd qa
  2. 设置基本权限

    设置属主、属组和 SGID
    $ sudo chown root:webdev /opt/webapp
    $ sudo chmod 2770 /opt/webapp
  3. 设置 ACL

    qa 组只读权限
    $ sudo setfacl -m g:qa:rx /opt/webapp
    deployer 用户完整权限
    $ sudo setfacl -m u:deployer:rwx /opt/webapp
  4. 设置默认 ACL(对新建文件生效)

    设置默认 ACL
    $ sudo setfacl -d -m g:webdev:rwx /opt/webapp
    $ sudo setfacl -d -m g:qa:rx /opt/webapp
    $ sudo setfacl -d -m u:deployer:rwx /opt/webapp
  5. 验证

    查看完整的 ACL 设置
    $ getfacl /opt/webapp

ACL 是对基本权限的扩展。当两者同时存在时:

  • 文件属主的权限仍由 user:: 控制
  • 其他用户的权限受 ACL 规则和 mask 共同影响
  • chmod 修改组权限时会影响 mask 值

文件属主已经是 root,为什么普通用户还能读取

Section titled “文件属主已经是 root,为什么普通用户还能读取”

因为 other(其他用户)的权限允许读取。例如权限 644 意味着所有用户都可以读取。

如何检查为什么某个用户无法访问文件

Section titled “如何检查为什么某个用户无法访问文件”
检查文件权限和 ACL
$ ls -la /path/to/file
$ getfacl /path/to/file
检查目录链上每一级的权限
$ namei -l /path/to/file

namei -l 会显示路径中每一级目录的权限,帮助你找到哪一级阻止了访问。

备份 ACL 到文件
$ getfacl -R /opt/webapp > acl-backup.txt
从备份恢复 ACL
$ sudo setfacl --restore=acl-backup.txt