Linux 文件权限是系统安全的基石。系统中每个文件和目录都有所有者、所属组和一组权限标志,决定了谁可以读取、写入或执行它。掌握 chmod、chown 和 chgrp 对于任何使用服务器、容器或 CI/CD 流水线的开发者、系统管理员或 DevOps 工程师都至关重要。本指南全面涵盖从基本权限概念到高级 ACL 和实际故障排除的所有内容。
1. Linux 权限模型
Linux 使用自主访问控制(DAC)模型。每个文件和目录都有三类用户和三种权限类型:
用户类别
- 所有者 (u) — 文件的拥有者,通常是创建文件的用户。
- 组 (g) — 属于文件所属组的用户,便于团队协作。
- 其他人 (o) — 系统上的其他所有人。
- 所有人 (a) — 所有者 + 组 + 其他人的简写。
权限类型
- 读取 (r = 4) — 查看文件内容;列出目录条目。
- 写入 (w = 2) — 修改文件内容;在目录中创建、重命名或删除文件。
- 执行 (x = 1) — 以程序方式运行文件;进入(cd)目录。
注意:对于目录,读取表示可以列出内容,写入表示可以创建/删除条目,执行表示可以进入(cd)目录。一个有读取权限但没有执行权限的目录可以列出文件名但无法访问文件元数据。
2. 读取权限 — ls -la 输出详解
ls -la 命令显示详细的文件信息,包括权限。以下是如何读取输出:
$ ls -la
total 32
drwxr-xr-x 5 alice developers 4096 Feb 10 09:00 .
drwxr-xr-x 3 root root 4096 Jan 15 12:00 ..
-rw-r--r-- 1 alice developers 1234 Feb 10 08:55 README.md
-rwxr-xr-x 1 alice developers 2048 Feb 10 08:50 deploy.sh
drwxrwx--- 2 alice developers 4096 Feb 09 14:30 shared/
lrwxrwxrwx 1 alice developers 11 Feb 08 10:00 config -> config.yaml让我们分解一个典型的权限字符串:
-rwxr-xr-x 1 alice developers 2048 Feb 10 deploy.sh
│└┬┘└┬┘└┬┘ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ └─ filename
│ │ │ │ │ │ │ │ └─ modification date
│ │ │ │ │ │ │ └─ file size (bytes)
│ │ │ │ │ │ └─ group owner
│ │ │ │ │ └─ file owner
│ │ │ │ └─ hard link count
│ │ │ └─ other permissions: r-x (read + execute = 5)
│ │ └─ group permissions: r-x (read + execute = 5)
│ └─ owner permissions: rwx (read + write + execute = 7)
└─ file type: - (regular file)第一个字符表示文件类型:- 普通文件,d 目录,l 符号链接,b 块设备,c 字符设备。
接下来的 9 个字符分为三组,每组三个:所有者权限、组权限和其他人权限。每组显示读取 (r)、写入 (w) 和执行 (x) — 或破折号 (-) 表示未设置该权限。
3. chmod 数字(八进制)模式
在数字模式中,权限用三位(或包含特殊权限的四位)八进制数表示。每个数字是其权限值的总和:
Read (r) = 4
Write (w) = 2
Exec (x) = 1
None = 0
rwx = 4 + 2 + 1 = 7
rw- = 4 + 2 + 0 = 6
r-x = 4 + 0 + 1 = 5
r-- = 4 + 0 + 0 = 4
--- = 0 + 0 + 0 = 0计算方式:对每个类别将读取 (4) + 写入 (2) + 执行 (1) 相加。例如,rwxr-xr-- = 7 (4+2+1)、5 (4+0+1)、4 (4+0+0) = 754。
# Set permissions using numeric mode
chmod 755 script.sh # rwxr-xr-x
chmod 644 config.json # rw-r--r--
chmod 600 id_rsa # rw-------
chmod 400 server.crt # r--------
chmod 750 /opt/project # rwxr-x---
chmod -R 755 /var/www/html # Recursive for directory tree常用权限值
777777 (rwxrwxrwx) — 所有人完全访问。危险 — 生产环境中避免使用!755755 (rwxr-xr-x) — 所有者完全权限;组和其他人可读取和执行。目录和脚本的标准权限。750750 (rwxr-x---) — 所有者完全权限;组可读取/执行;其他人无权限。适合共享项目目录。700700 (rwx------) — 仅所有者完全访问。用于 ~/.ssh 目录。644644 (rw-r--r--) — 所有者可读写;其他人只读。普通文件的标准权限。600600 (rw-------) — 仅所有者可读写。用于私密配置和 SSH 密钥。400400 (r--------) — 仅所有者只读。用于证书和敏感只读数据。4. chmod 符号模式
符号模式允许你修改特定权限而不需要一次设置所有权限。语法是 chmod [谁][操作符][权限],其中:
- 谁: u(所有者)、g(组)、o(其他人)、a(所有人)
- 操作符: +(添加)、-(移除)、=(精确设置)
- 权限: r(读取)、w(写入)、x(执行)、X(仅在是目录或已有执行权限时添加执行)
# Add execute permission for owner
chmod u+x script.sh
# Remove write permission from group
chmod g-w config.json
# Set others to read-only
chmod o=r public.html
# Add read permission for all users
chmod a+r README.md
# Add execute for owner, remove write from group and others
chmod u+x,go-w deploy.sh
# Set owner=rwx, group=rx, others=nothing
chmod u=rwx,g=rx,o= project/
# Add execute only to directories (not files) recursively
chmod -R a+X /var/www/html
# Copy permissions from owner to group
chmod g=u shared-file.txt符号模式的优点是可以更改一个权限而不影响其他权限。这在脚本和自动化中特别有用。
5. chown — 更改文件所有者和组
chown 命令更改文件和目录的所有者和/或组。只有 root(或 sudo)可以更改文件所有权。这对于设置 Web 服务器、Docker 卷和共享项目目录至关重要。
语法和示例
chown 接受多种格式:
chown user file— 仅更改所有者chown user:group file— 更改所有者和组chown :group file— 仅更改组(与 chgrp 相同)chown -R user:group dir/— 递归更改目录及其所有内容
# Change owner to 'alice'
sudo chown alice report.pdf
# Change owner and group
sudo chown alice:developers project/
# Change only the group (equivalent to chgrp)
sudo chown :www-data /var/www/html
# Recursive change for an entire directory tree
sudo chown -R www-data:www-data /var/www/html
# Change owner only if currently owned by 'bob'
sudo chown --from=bob alice important-file.txt
# Match ownership of another file
sudo chown --reference=/var/www/html/index.html newfile.html
# Change ownership of symlink itself (not the target)
sudo chown -h alice symlink.txt
# Verbose mode — see what changes
sudo chown -Rv alice:developers /opt/project/常用 chown 选项
-v(详细模式)— 显示每个被更改的文件--reference=参考文件— 设置所有权与另一个文件匹配-h— 更改符号链接本身的所有权而非目标文件--from=旧用户— 仅在当前所有者匹配时才更改
6. chgrp — 更改组所有权
chgrp 命令更改文件的组所有权。虽然 chown :group 也可以做同样的事情,但 chgrp 有一个关键优势:普通用户可以用它将文件的组更改为自己所属的任何组,无需 root 权限。
# Change group to 'developers'
chgrp developers project-file.txt
# Recursive group change
chgrp -R www-data /var/www/html
# Match group of another file
chgrp --reference=existing-file.txt new-file.txt
# Check your groups
groups
# Output: alice developers docker sudo
# Verbose mode
chgrp -Rv developers /opt/project/在以下情况使用 chgrp:
- 只需要更改组(不需要更改所有者)
- 作为普通用户将组更改为你所属的组
- 在脚本中需要清晰表达意图时 — chgrp 明确传达了操作目的
7. 特殊权限 — SUID、SGID、Sticky Bit
除了标准的 rwx 权限,Linux 还有三种特殊权限位,用于修改文件和目录的行为方式。它们在八进制中表示为第四位(前导位)。
当设置在可执行文件上时,进程以文件所有者的权限运行,而不是执行者的权限。经典示例是 /usr/bin/passwd,它需要 root 权限来修改 /etc/shadow,但任何用户都可以运行。
在 ls -l 输出中,SUID 在所有者执行位显示为 s:-rwsr-xr-x。如果底层执行位未设置,则显示为大写 S。
# Set SUID
chmod 4755 /usr/local/bin/my-tool
chmod u+s /usr/local/bin/my-tool
# Verify — shows 's' in owner execute position
ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Mar 14 /usr/bin/passwd在可执行文件上,进程以文件的组身份运行。在目录上,目录内创建的新文件自动继承目录的组,而非创建者的主组。这对共享项目目录至关重要。
# Set SGID on a directory — new files inherit group
chmod 2775 /opt/shared-project
chmod g+s /opt/shared-project
# Verify — shows 's' in group execute position
ls -ld /opt/shared-project
drwxrwsr-x 2 root developers 4096 Feb 10 /opt/shared-project
# Now any file created inside inherits 'developers' group
touch /opt/shared-project/newfile.txt
ls -l /opt/shared-project/newfile.txt
-rw-r--r-- 1 alice developers 0 Feb 10 newfile.txt当设置在目录上时,只有文件所有者、目录所有者或 root 才能删除或重命名其中的文件 — 即使其他人有写权限。经典示例是 <code>/tmp</code>(权限 1777)。
# Set sticky bit
chmod 1777 /tmp
chmod +t /shared-uploads
# Verify — shows 't' in others execute position
ls -ld /tmp
drwxrwxrwt 15 root root 4096 Feb 10 /tmp查找具有特殊权限的文件
# Find all SUID files on the system
find / -perm -4000 -type f 2>/dev/null
# Find all SGID files
find / -perm -2000 -type f 2>/dev/null
# Find all files with sticky bit
find / -perm -1000 -type d 2>/dev/null
# Find SUID or SGID files (security audit)
find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -la {} \; 2>/dev/null8. umask — 默认权限掩码
umask 命令设置新建文件和目录的默认权限掩码。它通过从最大默认值(文件 666,目录 777)减去权限来工作。
计算公式:有效权限 = 最大默认值 - umask
# Check current umask
umask
0022
# Display in symbolic notation
umask -S
u=rwx,g=rx,o=rx
# Set umask for current session
umask 022 # Files: 644, Dirs: 755
umask 027 # Files: 640, Dirs: 750
umask 077 # Files: 600, Dirs: 700
umask 002 # Files: 664, Dirs: 775
# Example: umask 022
# New file: 666 - 022 = 644 (rw-r--r--)
# New directory: 777 - 022 = 755 (rwxr-xr-x)
# Example: umask 077
# New file: 666 - 077 = 600 (rw-------)
# New directory: 777 - 077 = 700 (rwx------)常见 umask 值:
- 022 — 文件获得 644,目录获得 755。最常见的默认值。
- 027 — 文件获得 640,目录获得 750。更严格;其他人无权限。
- 077 — 文件获得 600,目录获得 700。非常严格;仅所有者有权限。
- 002 — 文件获得 664,目录获得 775。适合共享开发的组友好设置。
要使 umask 持久化,将其添加到 ~/.bashrc、~/.profile 或系统范围的 /etc/profile 中。
# Make umask persistent — add to ~/.bashrc or ~/.profile
echo 'umask 022' >> ~/.bashrc
# System-wide default — add to /etc/profile
echo 'umask 027' | sudo tee -a /etc/profile9. ACL — 访问控制列表
标准 Linux 权限(用户/组/其他人)每个文件只允许一个所有者和一个组。当你需要更精细的访问控制时 — 例如给特定用户读取权限而不更改文件的组 — 你需要 ACL(访问控制列表)。
使用 getfacl 读取 ACL
# View ACL of a file
getfacl report.txt
# file: report.txt
# owner: alice
# group: developers
user::rw-
user:bob:r--
group::r--
group:designers:rw-
mask::rw-
other::---
# View ACL of a directory (includes default ACLs)
getfacl /opt/shared-project/使用 setfacl 设置 ACL
# Grant read access to a specific user
setfacl -m u:bob:r report.txt
# Grant read+write to a specific group
setfacl -m g:designers:rw report.txt
# Remove ACL for a specific user
setfacl -x u:bob report.txt
# Remove all ACLs
setfacl -b report.txt
# Recursive ACL change
setfacl -Rm u:bob:rx /opt/project/默认 ACL 应用于目录内新建的文件和子目录。它们作为 ACL 模板:
# Set default ACL on a directory — new files inherit these
setfacl -d -m u:bob:rx /opt/shared-project/
setfacl -d -m g:designers:rw /opt/shared-project/
# View default ACLs
getfacl /opt/shared-project/
# default:user:bob:r-x
# default:group:designers:rw-在以下情况使用 ACL:
- 多个用户/组需要对同一文件有不同的访问级别
- 你不能或不想创建新的系统组
- Web 应用需要访问其他用户拥有的文件
有 ACL 的文件在 ls -l 的权限字符串末尾显示 +:-rw-r--r--+
10. 常见权限配置
以下是常见场景的生产就绪权限配置:
Web 服务器文件(Nginx / Apache)
# Nginx / Apache web root
sudo chown -R www-data:www-data /var/www/html
sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;
# Upload directory (needs write for web server)
sudo chmod 775 /var/www/html/uploads
sudo chown www-data:www-data /var/www/html/uploads
# PHP/Python application with write-protected code
sudo chown -R deploy:www-data /var/www/app
sudo find /var/www/app -type d -exec chmod 750 {} \;
sudo find /var/www/app -type f -exec chmod 640 {} \;
sudo chmod 770 /var/www/app/storage
sudo chmod 770 /var/www/app/cacheSSH 密钥权限
# SSH directory and key permissions (STRICT — SSH refuses otherwise)
chmod 700 ~/.ssh # drwx------
chmod 600 ~/.ssh/id_rsa # -rw------- (private key)
chmod 644 ~/.ssh/id_rsa.pub # -rw-r--r-- (public key)
chmod 600 ~/.ssh/authorized_keys # -rw-------
chmod 600 ~/.ssh/config # -rw-------
chmod 644 ~/.ssh/known_hosts # -rw-r--r--可执行脚本
# Make a script executable
chmod +x deploy.sh
chmod 755 /usr/local/bin/my-tool
# Cron scripts
chmod 750 /etc/cron.daily/backup-script
# Remove execute bit for safety when not needed
chmod -x data-file.csv日志文件
# Application logs — readable by group, not others
chmod 640 /var/log/myapp/*.log
chown root:adm /var/log/myapp/*.log
# Log directory
chmod 750 /var/log/myapp
chown root:adm /var/log/myapp
# Logrotate creates new files with these permissions
# In /etc/logrotate.d/myapp:
# create 640 root adm共享项目目录
# Create a shared project directory with SGID
sudo mkdir /opt/project
sudo chown root:developers /opt/project
sudo chmod 2775 /opt/project
# SGID (2) ensures new files inherit 'developers' group
# All members of 'developers' group can read/write
# Files created by any team member are group-accessible
# Add a user to the group
sudo usermod -aG developers alice
# User must log out and back in for group change to take effect11. 安全最佳实践
文件权限是你的第一道防线。遵循以下原则保护系统安全:
- 最小权限原则:授予所需的最低权限。从严格开始,仅在必要时放宽。
- 永远不要使用 777:生产环境中几乎没有使用 777 的正当理由。如果你认为需要它,你可能需要的是修复所有权。
- 定期审计 SUID/SGID 文件:这些是权限提升的攻击向量。使用
find来发现它们。 - 明智地使用组:不要向"其他人"开放权限,而是将用户添加到适当的组。
- 保护敏感文件:SSH 密钥 (600)、含密码的配置文件 (600)、TLS 证书私钥 (600)。
- 谨慎使用递归 chmod:运行
chmod -R前务必仔细检查路径。一个拼写错误可能破坏你的系统。 - 监控权限变更:在生产环境中使用 auditd 记录文件权限变更。
# Security audit commands
# Find all world-writable files
find / -type f -perm -002 -not -path '/proc/*' 2>/dev/null
# Find all SUID executables (potential privilege escalation)
find / -perm -4000 -type f 2>/dev/null
# Find files with no owner (orphaned files)
find / -nouser -o -nogroup 2>/dev/null
# Find files writable by others in sensitive directories
find /etc /usr -type f -perm -002 2>/dev/null
# Check for files with 777 permissions
find / -type f -perm 0777 2>/dev/null | head -2012. 常见权限问题排查
权限错误是 Linux 系统中最常见的问题之一。以下是最常见的问题及其解决方案:
"Permission denied" 错误
最常见的权限错误。按以下顺序检查:
- 1. 检查文件权限:
ls -la /path/to/file - 2. 检查目录权限(你需要对每个父目录都有执行权限)
- 3. 检查文件所有权:运行的用户/组是否匹配?
- 4. 检查 ACL:
getfacl /path/to/file - 5. 检查 SELinux 或 AppArmor:
ls -Z /path/to/file
# Systematic debugging of "Permission denied"
# Step 1: Check file permissions and ownership
ls -la /path/to/file
# Step 2: Check every parent directory (need 'x' on all)
namei -l /path/to/file
# Step 3: Check who you are running as
whoami
id
# uid=1000(alice) gid=1000(alice) groups=1000(alice),27(sudo),33(www-data)
# Step 4: Check ACLs
getfacl /path/to/file
# Step 5: Check SELinux context (if enabled)
ls -Z /path/to/file
getenforcesudo 与修复所有权的对比
用 sudo 绕过权限错误是一个坏习惯。应该修复根本原因:
- 不好:
sudo vim /var/www/html/index.html(会创建 root 所有的文件) - 正确:
sudo chown -R www-data:www-data /var/www/html然后正常编辑
# Fix web files created with wrong ownership
sudo chown -R www-data:www-data /var/www/html
sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;
# Fix home directory permissions
sudo chown -R $USER:$USER ~/
chmod 700 ~/Docker 文件权限问题
Docker 容器内部通常以 root 运行,导致宿主机上的文件为 root 所有。常见解决方案:
# Problem: container creates root-owned files on host
docker run -v $(pwd)/data:/app/data myimage
ls -la data/
# -rw-r--r-- 1 root root 1234 Feb 10 output.txt <-- root owned!
# Solution 1: Run container as current user
docker run --user $(id -u):$(id -g) -v $(pwd)/data:/app/data myimage
# Solution 2: In Dockerfile, create and use non-root user
# FROM node:20
# RUN groupadd -g 1000 appuser && useradd -u 1000 -g appuser appuser
# USER appuser
# Solution 3: In docker-compose.yml
# services:
# app:
# user: "1000:1000"
# volumes:
# - ./data:/app/data
# Solution 4: Fix permissions in entrypoint
# ENTRYPOINT ["sh", "-c", "chown -R appuser:appuser /app/data && exec su-exec appuser $@"]试试我们的交互式 Chmod 计算器工具
Chmod 计算器 →FAQ
chmod、chown 和 chgrp 有什么区别?
chmod 更改文件权限(读取、写入、执行)。chown 更改文件所有者,可选地同时更改组。chgrp 仅更改组所有权。chmod 控制允许什么操作,而 chown 和 chgrp 控制权限类别适用于谁。
为什么不能在没有 sudo 的情况下 chown 文件?
只有 root 可以更改文件所有权。这是一项安全措施 — 如果普通用户可以转让文件所有权,他们就可以绕过磁盘配额并创建看似属于其他用户的文件。但是,你可以不用 sudo 使用 chgrp 将文件的组更改为你所属的任何组。
-rwsr-xr-x 中的 "s" 是什么意思?
所有者执行位中的小写 "s" 表示已设置 SUID(设置用户 ID)位。这意味着无论谁执行该程序,它都以文件所有者的权限运行。例如,/usr/bin/passwd 设置了 SUID,这样普通用户就可以更新 /etc/shadow(由 root 拥有)。
如何找到所有 777 权限的文件?
运行:find / -type f -perm 0777 2>/dev/null。要查找并修复:find /var/www -type f -perm 0777 -exec chmod 644 {} \;。对于目录:find /var/www -type d -perm 0777 -exec chmod 755 {} \;。定期审计 777 权限是安全最佳实践。
如何解决 Docker 挂载卷的 "Permission denied"?
这是因为容器用户 UID 与宿主机用户 UID 不同。解决方案:1) 使用 --user 标志:docker run --user $(id -u):$(id -g)。2) 在 Dockerfile 中设置所有权:RUN chown -R appuser:appuser /app。3) 使用命名卷代替绑定挂载。4) 让容器和宿主机用户的 UID 匹配。