Linux: 文件权限——chmod / chown / umask 全解

Linux 是一个多用户操作系统。文件权限是它安全模型的基础——控制谁可以读、写、执行每个文件和目录。

📋 前置知识:需要先掌握以下内容

1. 你将学到


2. 一个 "Permission denied" 的故事

(1) 痛点:写好的脚本运行不了

小明写了一个 deploy.sh 脚本,想运行它时却遇到:

BASH
./deploy.sh
# bash: ./deploy.sh: Permission denied

他检查了文件权限:

TEXT 📖 仅展示
ls -l deploy.sh
# -rw-r--r-- 1 charlie charlie 50 Jul 7 10:23 deploy.sh

(2) 加一个执行权限

Bob 说:"你的脚本有读写权限,但没有执行权限。加一个 +x 就行。"

BASH
chmod +x deploy.sh
ls -l deploy.sh
# -rwxr-xr-x 1 charlie charlie 50 Jul 7 10:23 deploy.sh

./deploy.sh     # 这次成功了!

(3) 收益:理解了 Linux 权限体系

小明从此理解了 chmod +x 的含义。更重要的是,他开始理解 Linux 为什么安全——每个文件、每个用户都有明确的权限边界。


3. 知识点讲解

(1) rwx 权限模型

ls -l 输出的第一列就是权限信息。例如 -rwxr-xr-x

TEXT 📖 仅展示

-  rwx  r-x  r-x
│  └┬─┘ └┬─┘ └┬─┘
│   │    │    └── 其他人 (other) 权限
│   │    └─────── 所属组 (group) 权限
│   └──────────── 文件所有者 (user) 权限
└──────────────── 文件类型 (- 普通文件 / d 目录 / l 链接)

三个权限位的含义:

权限 字符 数值 对文件 对目录
r 4 查看文件内容 列出目录内容(ls)
w 2 修改文件内容 创建/删除目录中的文件
执行 x 1 运行文件(脚本/程序) 进入目录(cd 到其中)

(2) chmod 数字法

三位数字对应 User / Group / Other 的权限:

数字 二进制 权限
7 111 rwx(读+写+执行)
6 110 rw-(读+写)
5 101 r-x(读+执行)
4 100 r--(只读)
3 011 -wx(写+执行)
2 010 -w-(只写)
1 001 --x(只执行)
0 000 ---(无权限)

常用权限组合:

BASH
chmod 755 script.sh    # rwxr-xr-x 所有者可读写执行,其他人只读执行
chmod 644 file.txt     # rw-r--r--  所有者可读写,其他人只读

> 💡 **提示**:记住两个最常用的权限组合——755 是脚本标准权限(所有者可执行,其他人只读执行),644 是普通文件标准权限(所有者可读写,其他人只读)。755 和 644 的区别只在于"执行"位。
chmod 700 private.sh   # rwx------  仅所有者可操作
chmod 600 secret.txt   # rw-------  仅所有者可读写
chmod 777 public/      # rwxrwxrwx  所有人可操作(⚠️ 不安全)
⚠️ 注意chmod 777 让所有用户都能读写执行,这在服务器上极其危险——任何账号被攻破,攻击者都可以修改该文件。生产环境永远不要使用 777,应该用组权限(如 775)或 ACL 来解决共享问题。

(3) chmod 符号法

BASH
# 语法:chmod [谁][操作][权限] 文件
# 谁:u(所有者)/ g(组)/ o(其他人)/ a(全部)
# 操作:+(添加)/ -(移除)/ =(设置为)

chmod u+x script.sh    # 给所有者添加执行权限
chmod g-w file.txt     # 移除组的写权限
chmod o-r private.txt  # 移除其他人的读权限
chmod a+x script.sh    # 给所有人添加执行权限
chmod u=rwx,g=rx,o=r  # 等同于 754

(4) chown——修改所有者和组

BASH
# 修改文件所有者
sudo chown alice file.txt

# 修改文件所属组
sudo chown :developers file.txt

# 同时修改所有者和组
sudo chown alice:developers file.txt

# 递归修改目录及其内容
sudo chown -R alice:developers /srv/project/

(5) umask——默认权限掩码

当你创建新文件或目录时,Linux 会减去 umask 值得到默认权限。

TEXT 📖 仅展示
# 查看当前 umask
umask
# 输出:0022

# 默认权限计算:
# 文件最大:666(rw-rw-rw-)
# 目录最大:777(rwxrwxrwx)
# 减去 umask 022:
# 文件默认:666 - 022 = 644(rw-r--r--)
# 目录默认:777 - 022 = 755(rwxr-xr-x)

# 修改 umask
umask 007    # 更严格的默认权限
umask 000    # 所有用户可写(不安全)
💡 提示:umask 的计算不是简单的减法——而是权限位的"遮罩"。文件最大权限是 666(不给执行),目录最大权限是 777。umask 022 意味着去掉"组"和"其他人"的写权限,得到文件 644、目录 755,这是最安全的默认值。

(6) 特殊权限

特殊权限 数值 文件上的效果 目录上的效果
SUID 4xxx 以文件所有者身份运行 (无)
SGID 2xxx 以文件所属组身份运行 新文件继承目录的组
Sticky Bit 1xxx (无) 仅文件所有者可删除
⚠️ 注意:SUID/SGID 程序以文件所有者或组的权限运行,如果程序存在漏洞,攻击者可以借此提权到 root。只对必要的程序(如 /usr/bin/passwd)设置 SUID,并定期审计系统中的 SUID 文件:find / -perm -4000 -type f 2>/dev/null

BASH
# 设置 SUID(4)
chmod u+s /usr/bin/passwd    # passwd 以 root 身份运行
chmod 4755 /usr/bin/program  # 数字法设置 SUID

# 设置 SGID(2)
chmod g+s /srv/shared        # 在此目录创建的文件继承组
chmod 2775 /srv/shared       # 数字法设置 SGID

# 设置 Sticky Bit(1)
chmod +t /tmp                # 仅文件所有者可删除
chmod 1777 /tmp              # /tmp 目录的标准权限

▶ 示例:查看文件权限

BASH
# 长格式查看权限
ls -l /etc/passwd
# -rw-r--r-- 1 root root 2845 Jul  7 10:23 /etc/passwd

# 查看目录权限
ls -ld /tmp
# drwxrwxrwt 1 root root 4096 Jul  7 10:23 /tmp
# 最后的 t 表示 Sticky Bit

# 递归查看目录权限
ls -laR /srv/project | head -20

输出:

TEXT 📖 仅展示
/srv/project:
total 16
drwxr-xr-x 3 alice developers 4096 Jul  7 10:23 .
drwxr-xr-x 4 root  root       4096 Jul  7 09:00 ..
-rw-r--r-- 1 alice developers  256 Jul  7 10:23 config.yaml
-rwxr-xr-x 1 alice developers  512 Jul  7 10:23 deploy.sh
drwxr-xr-x 2 alice developers 4096 Jul  7 10:23 src

▶ 示例:chmod 数字法

BASH
# 755——标准脚本权限
chmod 755 deploy.sh
ls -l deploy.sh
# -rwxr-xr-x

# 644——标准文件权限
chmod 644 index.html
ls -l index.html
# -rw-r--r--

# 600——私密文件
chmod 600 private.key
ls -l private.key
# -rw-------

输出:

TEXT 📖 仅展示
-rwxr-xr-x 1 alice developers 512 Jul  7 10:23 deploy.sh
-rw-r--r-- 1 alice developers 256 Jul  7 10:23 index.html
-rw------- 1 alice developers 128 Jul  7 10:23 private.key

▶ 示例:chmod 符号法

BASH
# 添加执行权限
chmod +x script.sh    # 给所有人 +x(等价于 a+x)

# 只给所有者添加执行权限
chmod u+x script.sh

# 移除组和其他人的写权限
chmod go-w config.txt

# 为 shell 脚本设置标准权限
chmod u=rwx,g=rx,o=r script.sh
# 等同于 chmod 755 script.sh

输出:

TEXT 📖 仅展示
-rwxr-xr-- 1 alice developers 512 Jul  7 10:23 script.sh

▶ 示例:chown 修改所有者

BASH
# 修改文件所有者
sudo chown www-data index.html

# 修改组
sudo chown :www-data /srv/www/

# 同时修改
sudo chown alice:developers project/

# 递归修改整个目录树
sudo chown -R alice:alice ~alice/

输出:

TEXT 📖 仅展示
-rw-r--r-- 1 www-data www-data 256 Jul  7 10:23 index.html
drwxr-xr-x 2 www-data www-data 4096 Jul  7 10:23 /srv/www/
drwxr-xr-x 3 alice developers 4096 Jul  7 10:23 project/

▶ 示例:umask 实战

BASH
# 查看当前 umask
umask
# 输出:0022

# 创建一个新文件测试
touch test.txt
ls -l test.txt
# -rw-r--r--    ← 644(666 - 022)

mkdir testdir
ls -ld testdir
# drwxr-xr-x   ← 755(777 - 022)

# 修改 umask 后创建
umask 0077
touch secret.txt
ls -l secret.txt
# -rw-------   ← 600(666 - 077)

输出:

TEXT 📖 仅展示
0022
-rw-r--r-- 1 alice alice 0 Jul  7 10:23 test.txt
drwxr-xr-x 2 alice alice 4096 Jul  7 10:23 testdir
-rw------- 1 alice alice 0 Jul  7 10:23 secret.txt

▶ 综合示例:部署 Web 应用的正确权限设置

BASH
# 假设 /var/www/myapp 是 Web 应用目录

# 1. 设置所有者和组
sudo chown -R www-data:www-data /var/www/myapp

# 2. 目录权限:755(所有者可读写执行,其他人只读执行)
find /var/www/myapp -type d -exec chmod 755 {} \;

# 3. 文件权限:644(所有者可读写,其他人只读)
find /var/www/myapp -type f -exec chmod 644 {} \;

# 4. 可执行脚本:755
chmod 755 /var/www/myapp/deploy.sh

# 5. 敏感文件:600
chmod 600 /var/www/myapp/.env

# 6. 上传目录:目录可写
chmod 775 /var/www/myapp/uploads

❓ 常见问题

Q: 为什么 chmod 777 是不安全的? A: chmod 777 让所有用户都能读写执行该文件。如果任何一个账号被攻破,攻击者都可以修改或删除该文件,造成提权风险。生产环境应使用组权限(如 775)或 ACL 来解决共享问题,而非 777。

Q: 为什么创建的文件默认是 644 不是 755? A: 因为安全原则——新文件默认不给执行权限。Linux 认为大多数文件不需要执行权限,如果你需要执行,用 chmod +x 显式添加。

Q: 为什么我 SSH 登录后不能写入 /etcA: /etc 属于 root 用户,普通用户只有读权限(r-x)。要修改 /etc 下的文件,必须用 sudo 提权。这是一项保护系统的安全设计。

Q: SUID 程序有什么风险? A: SUID 程序以文件所有者(通常是 root)权限运行。如果 SUID 程序存在漏洞,普通用户可以提权到 root。因此 SUID 应该只设置给必要的程序(如 passwdping),而且应该定期审计。

Q: chmod -R 755 对目录递归安全吗? A: 视情况而定。如果目录中有脚本文件,755 是合理的。但如果你用 find 区分文件和目录分别设置(644 文件 / 755 目录),更安全也更精确。


📖 小节


📝 作业

  1. 基础题(难度⭐):创建一个脚本,用 chmod +x 赋予执行权限后运行;再用数字法设置一个文件为 644,一个目录为 755
  2. 进阶题(难度⭐⭐):用符号法移除文件的组和其他人的所有权限,然后创建一个测试用户(sudo useradd testuser),用 chown 将文件所有权改给该用户
  3. 挑战题(难度⭐⭐⭐):创建一个共享目录,设置 SGID(chmod g+s)使新文件继承组,并用 find + chmod 批量将一个 Web 项目目录的文件设为 644、目录设为 755
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏