文件权限是 Linux
运维里最"基础但最容易踩坑"的部分:一边是权限不足导致服务起不来、脚本跑不动、
Web 应用 403
报错;另一边是权限给大了带来安全风险(任何人都能改配置、删日志、写
crontab)。要把它用对,需要的不只是记住
chmod 755,而是理解权限位在文件与目录上的语义差异(
r/w/x 对目录的含义与文件完全不同)、属主/属组/其他人的边界、以及
umask、 SUID/SGID 、 Sticky Bit
这些机制为什么会存在、什么场景下才该用。本篇会从最小概念集出发,系统讲清
rwx 的语义、数字/符号写法、chmod/chown
的典型用法与排错思路,并用常见场景(共享目录、可执行脚本、临时目录、安全加固)解释"该怎么给权限、给到什么程度",再补上
ACL 、chattr
这些扩展机制与实战排障清单,让你能把权限问题一次性定位并修正确。
Linux 权限模型: owner/group/others 三层架构
基本概念
Linux 是多用户系统,每个文件/目录都有三个身份属性:
- 属主( Owner, u):创建或被指定为文件/目录拥有者的用户( UID)
- 属组( Group, g):多个用户可以同属一个组,在组内具有共享权限( GID)
- 其他用户( Others, o):不属于该文件属主或属组的所有人
为什么要这么设计?
- 属主:文件的"所有者",通常有最高权限(如读写执行)
- 属组:适用于团队协作(如开发组、运维组),组内成员共享权限
- 其他用户:防止文件被任意用户访问(安全隔离)
三种权限位( rwx)
每个身份( u/g/o)都有三个权限位:
- r( read):读权限
- w( write):写权限
- x( execute):执行权限
示例:rwxr-xr-x
- 属主:
rwx(可读可写可执行) - 属组:
r-x(可读可执行,不可写) - 其他:
r-x(可读可执行,不可写)
转换为数字:
rwx= 4+2+1 = 7r-x= 4+0+1 = 5r-x= 4+0+1 = 5- 所以
rwxr-xr-x=755
rwx 在文件和目录上的语义差异(最容易踩的坑)
这是最容易混淆的点: rwx 在文件和目录上的含义完全不同。
对文件(普通文件)
| 权限 | 含义 | 示例 |
|---|---|---|
r |
可读取文件内容 | cat file.txt |
w |
可修改文件内容 | echo "new" > file.txt |
x |
可执行文件(脚本需要有 shebang 如 #!/bin/bash) |
./script.sh |
对目录
| 权限 | 含义 | 示例 |
|---|---|---|
r |
可列出目录内容(看到文件名) | ls dir |
w |
可在目录内创建、删除、重命名文件(通常需要
x) |
touch dir/newfile |
x |
可进入目录(cd)、访问目录内的文件(如果知道文件名) |
cd dir 或 cat dir/file.txt |
实际例子:
情况 1:目录有 r 但没有
x
1 | chmod 644 mydir # mydir 权限变成 rw-r--r--(没有 x) |
原因:没有 x
就不能进入目录,也不能访问目录内的文件。
情况 2:目录有 x 但没有
r
1 | chmod 311 mydir # mydir 权限变成 -wx--x--x(有 x 但没有 r) |
原因:有 x 就能进入和访问文件,但没有
r 就不能列出目录内容。
情况 3:目录有 w 但没有
x
1 | chmod 622 mydir # mydir 权限变成 rw--w--w-(有 w 但没有 x) |
原因:虽然有 w,但没有 x
就不能进入目录,也就不能在目录内操作。
结论:对目录来说,x
是最基本的权限(没有 x
就什么都干不了);w 通常需要配合 x 使用。
chmod:修改权限(数字和符号两种写法)
数字写法(快速且常用)
每个权限位对应一个数字:
r = 4w = 2x = 1
相加得到一个 3 位数( owner/group/others):
7 = rwx( 4+2+1)6 = rw-( 4+2)5 = r-x( 4+1)4 = r--( 4)0 = ---(无权限)
常见示例: 1
2
3
4chmod 755 script.sh # owner=rwx, group=r-x, others=r-x(可执行脚本)
chmod 644 file.txt # owner=rw-, group=r--, others=r--(普通文件)
chmod 600 secret.key # owner=rw-, group=---, others=---(私钥文件)
chmod 777 shared # owner=rwx, group=rwx, others=rwx(完全开放,不推荐)
符号写法(更安全,适合增量修改)
1 | chmod u+x script.sh # 给 owner 加上执行权限 |
递归修改: 1
2chmod -R 755 dir # 递归修改目录及其内容
chmod -R u+rwX,g+rX,o-rwx dir # 大写 X 只给目录和已有执行权限的文件加 x(避免所有文件都变成可执行)
什么时候用数字、什么时候用符号?
- 数字:适合"一次性设置到目标值"(如
chmod 644 file) - 符号:适合"增量修改"(如
chmod u+x script.sh),更安全(不会误改其他权限位)
chown:修改文件所有权
chown 用于修改文件的属主和属组。
基本用法: 1
2
3
4sudo chown newowner file # 只改属主
sudo chown newowner:newgroup file # 同时改属主和属组
sudo chown :newgroup file # 只改属组
sudo chown -R user:group dir # 递归修改目录及其内容
注意:
- 只有
root或文件的当前属主可以修改所有权 - 普通用户不能把文件"送给"别人(防止恶意占用别人的配额)
常见场景:
- Web
服务器目录:
sudo chown -R www-data:www-data /var/www/html - 共享项目目录:
sudo chown -R :developers /srv/project
umask:新建文件的默认权限
什么是 umask
umask 是 User File Creation
Mask(用户文件创建掩码),决定新建文件/目录的默认权限。
计算方法: 1. 默认权限(系统预设):
- 文件:
666( rw-rw-rw-,不包括执行权限,防止误执行) - 目录:
777( rwxrwxrwx,目录需要 x 才能进入)
- 实际权限 = 默认权限 - umask 值
示例( umask = 022):
- 文件:
666 - 022 = 644( rw-r--r--) - 目录:
777 - 022 = 755( rwxr-xr-x)
查看和设置 umask
查看当前 umask: 1
umask # 输出: 0022(第一位是特殊权限位,通常忽略)
临时设置 umask: 1
2umask 027 # 设置为 027
# 之后新建的文件权限是 640( 666-027),目录权限是 750( 777-027)
永久设置 umask(对当前用户): 编辑
~/.bashrc 或 ~/.zshrc,添加:
1
umask 027
常见 umask 值:
| umask | 文件权限 | 目录权限 | 适用场景 |
|---|---|---|---|
| 022 | 644 | 755 | 默认值(文件不被其他用户修改) |
| 027 | 640 | 750 | 更严格(仅允许同组用户访问),生产环境推荐 |
| 002 | 664 | 775 | 共享环境(允许同组用户修改),开发环境 |
| 077 | 600 | 700 | 极度严格(只有属主能访问),适合个人私密文件 |
特殊权限: SUID/SGID/Sticky Bit
这三种特殊权限位用于特定的运维需求,理解它们的原理和使用场景很重要。
SUID( Set User ID)
原理
当可执行文件被赋予 SUID 权限后,普通用户执行该文件时,会以该文件的属主身份运行,而不是调用者自身的身份。
常见示例:/usr/bin/passwd
ls -l /usr/bin/passwd显示:-rwsr-xr-xroot root(注意 owner 的 x 变成了 s)- 普通用户执行
passwd时,以 root 身份运行,才能修改/etc/shadow(只有 root 能写)
为什么需要 SUID?
- 允许普通用户执行特定的需要高权限的操作(如修改自己的密码)
- 不需要给用户
sudo权限(更安全)
查看和设置
查看: 1
ls -l file # 如果属主的 x 位显示为 s(小写)或 S(大写),说明有 SUID
s(小写): SUID 且有执行权限S(大写): SUID 但没有执行权限(通常是配置错误)
设置 SUID: 1
2chmod u+s myprog # 符号写法
chmod 4755 myprog # 数字写法( 4 表示 SUID, 755 是基础权限)
去除 SUID: 1
chmod u-s myprog
实战示例
假设你有一个 C 程序 myprog.c: 1
2
3
4
5
6
7
8
9
int main() {
printf("Real UID=%d, Effective UID=%d\n", getuid(), geteuid());
system("id");
return 0;
}
编译并设置 SUID: 1
2
3gcc -o myprog myprog.c
sudo chown root myprog # 属主改为 root
sudo chmod 4755 myprog # 设置 SUID + 755
普通用户执行: 1
./myprog
输出示例: 1
2Real UID=1000, Effective UID=0
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user)
- Real UID 是当前用户( 1000)
- Effective UID 是文件属主( 0=root)
- 所以程序以 root 权限运行
安全注意事项
SUID 是高风险的:
- SUID 程序一旦有漏洞(如缓冲区溢出、命令注入),攻击者可以获得 root 权限
- 避免对不可信的程序设置 SUID
- 定期审计系统中的 SUID 程序
查找系统中所有 SUID 程序: 1
find / -perm -4000 -type f 2>/dev/null
常见的 SUID 程序(这些是合理的):
/usr/bin/passwd:修改密码/usr/bin/sudo:临时提权/usr/bin/mount:挂载文件系统/usr/bin/ping:发送 ICMP 包(需要 raw socket 权限)
SGID( Set Group ID)
应用场景
SGID 有两种用法:
1. 对可执行文件
进程运行时,其有效组 ID( GID)替换为文件的属组。这在需要访问特定组资源的工具中很常见。
2. 对目录(更常用)
当目录设置 SGID 后,在此目录中新建的文件或子目录会继承该目录的组,而非创建者的默认组。这非常适合团队共享目录。
示例: 1
2
3sudo mkdir /srv/project
sudo chown :developers /srv/project # 属组改为 developers
sudo chmod 2775 /srv/project # 设置 SGID + 775( 2 表示 SGID)
现在,任何 developers 组的成员在 /srv/project
里创建的文件,属组都自动是
developers,组内其他成员也能访问。
查看和设置
查看: 1
ls -l file # 如果属组的 x 位显示为 s(小写)或 S(大写),说明有 SGID
设置 SGID: 1
2chmod g+s shared_dir # 符号写法
chmod 2775 shared_dir # 数字写法( 2 表示 SGID)
去除 SGID: 1
chmod g-s shared_dir
Sticky Bit(粘滞位)
作用与原理
Sticky Bit 最常见于多用户可写的公共目录,如
/tmp。当目录设置 Sticky Bit
后,该目录中的文件只能被其属主或 root
删除或改名,即使其他人对该目录也有写权限。
为什么需要 Sticky Bit?
/tmp是所有用户共享的临时目录,权限是1777( rwxrwxrwt)- 如果没有 Sticky Bit,用户 A 可以删除用户 B 的临时文件(安全风险)
- 有了 Sticky Bit,用户 A 只能删除自己的文件,不能删除用户 B 的文件
查看和设置
查看: 1
ls -ld /tmp # 输出: drwxrwxrwt(最后一位是 t)
设置 Sticky Bit: 1
2chmod o+t dirname # 符号写法
chmod 1777 /tmp # 数字写法( 1 表示 Sticky Bit)
去除 Sticky Bit: 1
chmod o-t dirname
常见场景与最佳实践
场景 1:可执行脚本
问题:./script.sh: Permission denied
排查: 1
ls -l script.sh # 查看权限
如果显示 -rw-r--r--(没有 x),说明没有执行权限。
解决: 1
2
3chmod +x script.sh # 给所有人加上执行权限
# 或
chmod 755 script.sh # owner=rwx, group=r-x, others=r-x
注意:脚本还需要有 shebang(如
#!/bin/bash),否则需要用 bash script.sh
运行。
场景 2: Web 服务器目录
需求: Nginx/Apache 需要读取
/var/www/html 里的文件。
排查: 1
2ls -ld /var/www /var/www/html
ls -l /var/www/html/index.html
常见问题:
- 目录权限不足( Nginx 用户没有 x 权限,不能进入)
- 文件权限不足( Nginx 用户没有 r 权限,不能读取)
解决: 1
2
3
4
5sudo chown -R www-data:www-data /var/www/html # 属主改为 www-data
sudo chmod -R 755 /var/www/html # 目录和文件都设为 755
# 或者更严格
sudo find /var/www/html -type d -exec chmod 755 {} \; # 目录 755
sudo find /var/www/html -type f -exec chmod 644 {} \; # 文件 644
场景 3:共享目录(团队协作)
需求:/srv/project 目录, developers
组的成员都能读写,其他人不能访问。
方案: 1
2
3sudo mkdir /srv/project
sudo chown :developers /srv/project # 属组改为 developers
sudo chmod 2770 /srv/project # SGID + 770(只有 owner 和 group 能访问)
2: SGID(新建文件自动继承 developers 组)770: owner 和 group 都是 rwx, others 无权限
验证: 1
2
3# 用户 A( developers 组成员)创建文件
touch /srv/project/fileA
ls -l /srv/project/fileA # 输出:-rw-r--r-- userA developers
文件属组自动是 developers,组内其他成员也能访问。
场景 4:临时目录(防止互删文件)
需求:/tmp
目录,所有用户都能创建文件,但不能删除别人的文件。
方案: 1
sudo chmod 1777 /tmp # Sticky Bit + 777
1: Sticky Bit(只有属主和 root 能删除文件)777:所有用户都能读写执行
扩展机制: ACL 和 chattr
ACL( Access Control Lists)
为什么需要 ACL?
- 传统权限只能设置 owner/group/others 三层,不够灵活
- ACL 可以为特定用户或特定组设置权限(如"用户 A 有读权限,用户 B 有写权限")
查看 ACL: 1
getfacl file.txt
设置 ACL: 1
2
3
4setfacl -m u:alice:rw file.txt # 给用户 alice 读写权限
setfacl -m g:dev:rx dir # 给组 dev 读执行权限
setfacl -x u:alice file.txt # 移除用户 alice 的 ACL
setfacl -b file.txt # 移除所有 ACL
递归设置: 1
setfacl -R -m u:alice:rwx dir # 递归设置
chattr:文件属性(防止误删/误改)
chattr 可以设置文件的特殊属性( ext4
文件系统支持)。
常用属性:
i( immutable):文件不可修改、删除、重命名(连 root 也不行,除非先去掉 i 属性)a( append-only):文件只能追加写入,不能修改已有内容(适合日志文件)
设置不可修改: 1
2
3sudo chattr +i important.conf # 文件变成不可修改
rm important.conf # ❌ Operation not permitted(连 root 也删不掉)
sudo chattr -i important.conf # 去掉 i 属性后才能删
设置只能追加: 1
2
3sudo chattr +a logfile.txt # 只能追加
echo "new line" >> logfile.txt # ✅ 可以追加
echo "overwrite" > logfile.txt # ❌ Operation not permitted(不能覆盖)
查看属性: 1
lsattr file.txt
使用场景:
- 保护重要配置文件(
/etc/fstab、/etc/passwd) - 防止日志文件被清空
chattr 的其他属性:
d( no dump):备份时忽略该文件s( secure deletion):删除时用 0 填充数据(安全删除)u( undeletable):删除后内容可恢复
示例:保护 /etc/fstab 不被误删
1
2
3sudo chattr +i /etc/fstab
rm /etc/fstab # ❌ Operation not permitted
sudo chattr -i /etc/fstab # 需要先解除保护
权限排障清单:出问题了怎么办
问题
1:Permission denied
排查步骤: 1.
确认执行用户:whoami(或查看服务的运行用户,如 systemd unit
文件) 2. 查看文件权限:ls -l file 3.
查看所有父目录权限:namei -l /full/path/to/file(需要安装
util-linux 包) 4.
检查组成员:id(看当前用户属于哪些组) 5.
检查特殊属性:lsattr file(是否有 i 或
a 属性)
常见原因:
- 文件没有读/写/执行权限
- 父目录没有 x 权限(不能进入)
- 用户不在文件的属组里
解决: 1
2
3
4sudo chmod 644 file # 给读权限
sudo chmod +x script.sh # 给执行权限
sudo chmod 755 /path/to/parent/dir # 给父目录 x 权限
sudo chown user:group file # 修改所有权
问题 2: Web 服务器 403 Forbidden
原因: Nginx/Apache 用户(如
www-data、nginx)没有权限读取文件。
排查: 1
2
3ps aux | grep nginx # 查看 nginx 运行用户
ls -l /var/www/html/index.html # 查看文件权限
namei -l /var/www/html/index.html # 查看所有父目录权限
解决: 1
2
3sudo chown -R www-data:www-data /var/www/html
sudo chmod -R 755 /var/www/html # 目录 755
sudo find /var/www/html -type f -exec chmod 644 {} \; # 文件 644
问题 3:脚本执行失败
原因:脚本没有执行权限或 shebang 错误。
排查: 1
2ls -l script.sh # 查看权限
head -1 script.sh # 查看 shebang
解决: 1
2chmod +x script.sh # 加执行权限
# 确保 shebang 正确(如 #!/bin/bash)
问题
4:rm: cannot remove 'file': Operation not permitted
原因:文件可能有 i
属性(不可修改/删除)。
排查: 1
lsattr file
如果输出包含 i(如
----i--------),说明文件有 immutable 属性。
解决: 1
2sudo chattr -i file # 去掉 i 属性
rm file # 现在可以删除了
总结与扩展阅读
这篇文章涵盖了 Linux 文件权限的核心内容: 1. ✅ Linux 权限模型( owner/group/others 、 rwx 语义) 2. ✅ rwx 在文件和目录上的差异(最容易踩的坑) 3. ✅ chmod 和 chown 的使用(数字/符号写法) 4. ✅ umask 的原理和常见值(新建文件的默认权限) 5. ✅ 特殊权限( SUID/SGID/Sticky Bit 的原理和使用场景) 6. ✅ 扩展机制( ACL 、 chattr) 7. ✅ 权限排障清单( Permission denied 、 403 、脚本执行失败等)
扩展阅读:
man chmod:查看 chmod 的详细手册man chown:查看 chown 的详细手册man 5 acl:查看 ACL 的详细说明- SELinux / AppArmor:更高级的安全模型(强制访问控制 MAC)
下一步:
- 《 Linux
用户管理》:学习如何管理用户/组、
/etc/passwd、/etc/shadow、 sudo 配置 - 《 Linux 文件操作深入解析》:学习管道、重定向、
stdin/stdout/stderr 、
xargs、tee
到这里,建议已经从"会用 chmod 755"升级到"理解权限语义、能设计共享目录权限方案、能排查权限问题"。文件权限是 Linux 安全的基石,掌握了它,你就能更好地保护系统和数据。
- 本文标题:Linux 文件权限
- 本文作者:Chen Kai
- 创建时间:2019-11-20 09:45:00
- 本文链接:https://www.chenk.top/Linux-%E6%96%87%E4%BB%B6%E6%9D%83%E9%99%90/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!