Linux文件权限完全指南:从rwx到ACL,搞定Permission denied

发布时间:2026/10/1 12:20:32
Linux文件权限完全指南:从rwx到ACL,搞定Permission denied 1. 从“拒绝访问”说起为什么Linux权限决定你是否挨骂先讲个我早年带团队时几乎每周都遇到的事。新同事一脸无辜地跑来问“为什么我删不掉这个文件我可是root啊。”我过去一看要么是挂载盘上用的是root权限创建的文件要么是压根没理解Linux那套“三位一体”的权限模型。你问Windows用户他知道“需要trustedinstaller权限才能删除文件”是啥意思吗很多人也不清楚但Windows会弹窗告诉你“你权限不够”。Linux不一样多数时候它只会冷冷地给你一个Permission denied然后你自己琢磨去吧。当年我刚从Windows转Linux最痛苦的就是这一点。在Windows里你面对的是一个“谁都能做管理员”的模糊环境而Linux从骨子里就是一个多用户、多任务的操作系统每个文件、每个目录都有自己的归属和规则。这套规则的正式名称叫POSIX文件权限模型它看起来只有几行字母-rwxr-xr--但背后牵涉到用户、组、进程、安全策略、甚至内核的判定逻辑。今天这篇我打算掰开揉碎把Linux文件权限从入门到进阶从日常命令到踩坑实录全部梳理一遍。内容会覆盖三个层次第一基础篇理解r/w/x和u/g/o这三个分组以及chmod/chown/chgrp的每个细节第二进阶篇讲清楚setuid/setgid/sticky bit、ACL访问控制列表、umask这几位“隐藏大佬”第三实战篇聊聊为什么sudo不能解决所有问题、Permission denied的完整排查路径、以及文件权限修复的几种靠谱方案。无论是刚接触Linux的新手还是被权限问题折磨的运维这篇都值得你收藏慢慢看。2. 基础篇先搞懂那串“-rwxr-xr--”到底在说什么2.1 三组权限位所有者、用户组、其他人的“三权分立”如果你打开终端敲一下ls -l看到的每一行开头都有类似这样的内容-rw-r--r-- 1 root root 1024 Jan 1 10:00 test.conf drwxr-xr-x 2 root root 4096 Jan 1 10:00 scripts第一个字符代表文件类型-表示普通文件d表示目录后面还有l软链接、c字符设备、b块设备等特殊类型。今天重点说权限位。剩下的9个字符分成三组每组的含义都是r读、w写、x执行第1-3位属主owner对该文件的权限第4-6位属组group对该文件的权限第7-9位其他人others对该文件的权限打个比方就像你家公寓楼的三把钥匙你是房主owner你家人是一个编组group路人就是其他人others。房主可以配钥匙改锁rwx全是你的家人可能只有进入客厅的权利r-x能进不能改路人通常连门都进不去---啥也没有。每把钥匙的权限彼此独立Linux在处理访问请求时只会匹配一把钥匙既不叠加也不合并。一旦命中了第1组后面两组统统不看这就是“匹配即短路”的原则。这里有一个新手的核心误区很多人以为文件权限是从上到下三个组“加总”的比如owner是r--group是rw-那owner实际就有rw-了。完全不是这样的。系统判断时先看你是不是文件的属主是就直接看第一组不是再看你是不是属组成员是就看第二组都不是才轮到第三组。所以如果第一组只有r--哪怕你是root用普通方式也写不进这个文件——当然root可以忽略任何权限因为root就是“万能钥匙”。2.2 r/w/x在目录和文件上的含义不太一样这是重点很多人背了rwx含义但一到目录就懵。原因在于目录上的r/w/x和文件上的r/w/x代表的完全是两码事。先看文件r读可以查看文件内容比如cat、less、vim打开w写可以修改文件内容、覆盖写入、追加写入x执行可以将这个文件作为可执行程序运行比如脚本或二进制程序再看目录r读可以列出目录下有哪些文件名ls能看到文件列表w写可以在目录里创建、删除、重命名文件或子目录x执行可以进入该目录cd进去并且能访问目录内文件的元数据目录的x权限特别容易被忽视。你如果只给一个目录r但没给x那你ls运气好还能看到文件名列表但你要cd进去或者访问里面具体文件的内容就会报Permission denied。因为目录的执行权限本质上控制的是“你是否能够穿越这个目录”。我见过太多人部署完Nginx后发现404查半天是web根目录少了x权限Nginx的worker进程读不了文件。另一个典型坑是删除文件你不需要对文件本身有写权限你只需要对“它所在的目录”有写权限。这意味着一个只有r--的文件只要目录是rwx照样能被rm删除。反向操作也成立哪怕你对该文件有rwxrwxrwx的权限但所在目录你连w都没有你也删不掉它。这是最容易被新运维误解的地方。你登录进去明明看到自己对该文件有写权限却依然rm: cannot remove xxx: Permission denied赶紧检查目录权限别盯着文件死磕。3. 实操篇chmod、chown、chgrp——每天都要用的三条命令3.1 chmod的数字模式和符号模式到底用哪个chmod是修改权限的核心命令。它有两种表达方式我都强烈建议你熟练掌握。数字模式把每组权限压缩成一个数字。r4w2x1组合相加。比如rwx就是 4217r-x就是 415r--就是4。三组连写chmod 755 file表示owner是7rwxgroup是5r-xothers是5r-x。数学上这就是三组权限位的“八进制编码”每一位不会超过7和二进制位一一对应所以叫mode。符号模式用三组字母加运算符比如chmod ux file给owner加上执行权限、chmod g-w file给group去掉写权限、chmod or file给others设为只读、chmod ax file给所有人加上执行权限。这里的u是userg是groupo是othersa是all。我的实践建议是脚本和自动化场景用数字模式因为简洁、幂等不管之前是什么权限设置完就是同一个结果不会受原状态影响交互式排障时用符号模式因为更直观——你只是想让“当前用户”获得执行权限没必要把其他权限也重设一遍。我见过有人用chmod 777救急后把服务器目录脱了个精光也见过用chmod 666给配置文件开了写权限导致被篡改的事件。权限尽量最小化永远记住运维的第一原则不给多余权限不给意外权限。3.2 chown和chgrp把文件“送给”正确的用户和组chown用来修改文件的属主和属组用法是chown user:group file。比如部署一个web服务用户是www-data你希望/var/www/html里的文件属主是www-data属组是www-data那就一条命令搞定chown -R www-data:www-data /var/www/html-R是递归把目录下所有子目录和文件一起改。这里有个小提醒先用ls -l看一下当前属主属组再改。如果你手滑把系统关键文件的属主改成了自己的普通用户轻则服务失败重则系统起不来。比如/etc/shadow一旦属主不是root安全模型直接瘫痪。单独改属组用chgrp但这命令在日常中出镜率不高因为chown user:group一条就都改了。需要注意普通用户只能改自己文件的属组且目标组必须是你所属的组。只有root能自由地把文件转给任何用户、任何组。这个设计有它的道理否则A用户随手把文件属主改成B用户然后B用户就可能面临非预期的文件变动。3.3 umask你没主动设过的权限是它在背后控制每当你创建一个新文件系统不会默认给你rwxrwxrwx这种全开放权限也不会给个最低权限它要根据一个掩码来计算这个掩码就是umask。你可以敲umask查看当前值默认一般是0022。计算方式是从默认权限“最大值”中减去umask值。文件默认最大是666因为新建文件不允许有执行权限需要再通过chmod显式加x目录默认最大是777。所以umask为022时新建文件 666 - 022 644rw-r--r--新建目录 777 - 022 755rwxr-xr-xumask的值越小权限越大0000基本就是全放开了这在生产环境极其危险。你说我为什么要强调这个因为不少人不知情状态下把umask设成000导致所有新建文件都是666然后上一堆奇怪的漏洞——其实未必是漏洞只是你“刻意”开放了文件。修改umask可以在shell里临时执行umask 077想永久生效就写入/etc/profile或~/.bashrc。生产服务器建议umask 077或至少027组内成员也不该默认能看你的敏感文件。4. 进阶篇setuid、setgid、sticky bit——三个连老手都容易懵的权限4.1 setuid为什么普通用户改密码时能写 /etc/shadow来看一个经典问题/etc/shadow保存着用户密码哈希权限是-rw-------属主root普通用户理论上根本不能读不能写。但如果普通用户执行passwd修改自己密码为什么能改成功答案是/usr/bin/passwd这个程序上有个setuid位显示为-rwsr-xr-x。那个s就是setuid。当程序带setuid位时无论谁执行它进程的有效用户IDeffective UID会被临时提升为程序属主root。于是这个程序就能以root身份访问/etc/shadow按程序逻辑只允许用户改自己的密码。这就是为什么passwd程序本身带有极高的权限却不能随意给你cat out shadow内容——因为程序里写死了只修改当前用户对应的那行记录。setuid的查看和设置ls -l /usr/bin/passwd chmod us /path/to/program # 设置setuid chmod u-s /path/to/program # 移除setuid风险也在这里。如果你把一个可写的shell脚本加上setuid或者把一个带漏洞的二进制程序赋予setuid等于给普通用户一把通向root的后门。所以生产环境的原则是能用sudo解决的问题不要上setuid必须用setuid的严格限定程序来源和安全审计。4.2 setgid目录也可以“遗传”属组setgid用在文件上和setuid类似但提升的是有效组ID。用在目录上则有一个更实用的效果该目录下新建的文件或子目录其属组自动继承该目录的组而不是创建者的主组。比如你有一个共享目录/srv/teamdata属主是root属组是team。团队里每个人都需要往里面写文件但希望新文件都归team组所有这样同组人才能协作读写。此时给目录设置setgid位chmod gs /srv/teamdata设置后目录的显示会变成drwxrwsr-x。以后再有人往里面创建文件文件的group组自动是team而不是他个人的主组。这在多人协作的共享存储、git裸仓库、NFS共享目录里都极其实用属于标准姿势。4.3 sticky bit为什么 /tmp 里删不掉别人的文件/tmp目录人人都能写但你不能删别人的文件——这个限制就来自sticky bit。它的标志是目录权限最后一位变成t比如drwxrwxrwt。设置命令chmod t /tmpsticky bit的核心规则是目录如果设置了sticky bit只有文件属主、目录属主或root三者在“对该目录有写权限”的情况下才能删除或重命名目录内的文件。其他用户即使对该目录有写权限也不能动不属于自己的文件。试想没有sticky bit的/tmp是什么样的所有用户都能创建文件但也能互删文件。某个用户删掉另一个用户正在使用的临时文件或者往里面放一个同名恶意文件等着别人调用——安全性和可用性双双崩溃。所以/tmp和/var/tmp这类公共可写目录系统都会默认加上sticky bit。你自己搭建共享目录时如果希望用户能互相放文件但不能互相删文件也记得加个sticky bit。5. 深入篇ACL、sudo与文件属性那些比chmod更精细的权限控制5.1 ACL访问控制列表不只三个组的权限怎么办当三组权限不够用时——比如一个文件需要给两个不同的用户不同权限一个只读一个可写而他们不在同一个组——用chmod就无能为力了。这时你需要ACLAccess Control List访问控制列表。Linux的ACL通过setfacl和getfacl管理。典型操作# 查看文件的ACL getfacl myfile # 给用户alice赋予对myfile的读权限 setfacl -m u:alice:r myfile # 给组devgroup赋予读写权限 setfacl -m g:devgroup:rw myfile # 移除某个用户的所有ACL设置 setfacl -x u:alice myfile # 递归复制ACL到子文件目录 setfacl -R -m u:alice:r /data/share加了ACL之后你ls -l看权限位最后会多一个比如-rw-r-----提醒你这个文件还有额外的ACL条目。ACL虽然强大但排查问题也更复杂。我记得有次线上某个配置文件普通用户明明有ACL读权限程序还是Permission denied。查了好一阵才发现是父级目录少了x权限ACL设置只解决了文件本身没解决“穿越目录”的路径权限。所以ACL排障一定要沿着路径逐级检查。另一个注意点是ACL会让文件备份恢复变得复杂很多备份工具的默认行为不保留ACL恢复后权限会丢失需要额外加参数专门保存。5.2 sudo不是让你为所欲为只是让你“按规则为所欲为”很多新手把sudo当作“破解权限的万能钥匙”动不动就sudo vim /etc/xxx。实际上sudo的权限受/etc/sudoers文件严格约束。它解决的问题是在不共享root密码的情况下给指定用户授予指定的管理员操作权限。比如你是运维希望deploy用户能执行/usr/bin/systemctl restart nginx和/usr/bin/apt update但不能执行cat /etc/shadow更不能直接成为root。可在/etc/sudoers里配置deploy ALL(ALL) /usr/bin/systemctl restart nginx, /usr/bin/apt update这样deploy用户执行sudo systemctl restart nginx sudo apt update会被允许但sudo cat /etc/shadow会被拒绝。这才是sudo的正确打开方式。用visudo编辑配置文件会做语法检查避免你一个笔误把自己锁在外面。如果你不小心把用户加进wheel组或sudo组又不理解组内成员的sudo规则隐患极大——所以我建议先把/etc/sudoers里的注释和默认配置读一遍理解%wheel ALL(ALL) ALL到底意味着什么。还有一个高频坑普通用户执行sudo时有效uid变成root但环境变量不一定跟着切换。写脚本时如果你依赖$HOME或者$PATH可能得到和预期不同的路径。比如sudo env看到的PATH与env的PATH就可能有差异。5.3 lsattr和chattr让文件“不可动摇”的最后防线你可能不知道除了rwx之外还有一层“不可变属性”。通过chattr i可以让文件即使root也不能修改、删除、重命名这在某些安全场景下非常有用。chattr i /etc/myapp.conf lsattr /etc/myapp.conf加了i属性的文件任何写入、删除动作都会返回Operation not permitted。要移除属性用chattr -i。这个特性我在防篡改脚本、加固重要配置时经常用。但要注意这可能会带来误伤如果某个服务需要定期更新配置文件你一个chattr i把文件锁了服务可能会写失败然后整天报错。排查时如果发现一切权限都正常但仍无法写入/删除记得看一眼lsattr。我记得有次线上事故运维为了“保护”日志文件给日志目录加了i结果日志轮转脚本永远失败磁盘空间越涨越高——最后定位花了不少时间。6. 排查篇Permission denied的完整排查思路与命令速查6.1 六步定位法从路径到进程的完整排查顺序遇到Permission denied不要慌按照下面这个顺序逐步排查80%的问题都能定位确认当前身份用id或whoami看看你是谁属于哪些组。有时候你以为自己是以root操作实际上可能是某个普通用户。逐级检查路径权限对文件路径上的每个目录检查是否有执行权限x。上面提过路径上任一目录少了x就无法访问下级文件。检查目标文件本身的权限ls -l看属主和权限位确认和当前用户/组是否匹配。检查ACLgetfacl看有没有额外ACL条目。检查sudo规则如果你用的工具需要提权确认sudoers里是否允许当前用户执行该命令。检查文件属性lsattr看是否被加了i、a等不可变属性。我建议你把这套流程做成一个固定的肌肉记忆。有一次同事排查Nginx返回403绕了半天最后发现是从根目录到站点目录中间某个中间目录的权限是drwx------属主是另一个用户Nginx进程自然进不去。这就是典型的第2步问题。6.2 常见问题的速查与修复方案现象可能原因验证命令修复方案文件能ls但无法cat文件本身无读权限ls -lchmod r或调整属主目录能ls但无法cd目录无执行权限ls -ld dirchmod x dir能rm文件却提示Permission denied目录无写权限ls -ld 目录chmod w 目录无法删除公共目录下的别人文件目录没有sticky bitls -ld /tmp设置chmod t或检查文件属主普通用户改不了密码passwd的setuid位丢失ls -l /usr/bin/passwd修复setuid位能读文件但程序启动报Permission denied脚本无执行权限查看脚本权限位chmod x script.sh明明有rw权限但无法写入文件中了不可变属性lsattr filechattr -i filesudo命令报“不在sudoers中”用户未授权sudo查看/etc/sudoers用visudo添加规则很多人遇到问题第一反应是chmod 777。我强烈不建议尤其是配置文件或包含业务数据的目录。777会让所有系统用户都有完全控制权一旦服务器出现其他漏洞它就是敞开的保险箱。正确方式是用ls -l和getfacl找出具体缺什么缺读补读缺执行补执行面向最小权限原则去修。6.3 修复权限的三种场景及实操命令场景一业务目录的整体权限修复比如web目录/var/www/html被误操作成root:root 700导致web服务无法读取。修复思路是先设目录归属再彻底统一权限chown -R www-data:www-data /var/www/html find /var/www/html -type d -exec chmod 755 {} \; find /var/www/html -type f -exec chmod 644 {} \;目录统一755文件统一644这是Web目录最常见的标准模式。对目录和文件分开处理是因为如果直接chmod -R 755所有文件也会变成755等于把所有脚本都加了执行权限有轻微的安全风险——虽然不大但没必要。场景二找回/恢复关键系统权限如果chown或者chmod误操作导致某些关键系统目录权限错乱建议不要凭记忆手工挨个改。在生产环境优先考虑从备份恢复或者用相同版本的系统镜像启动后在挂载的状态下做比对修复。网上那些“一键修复脚本”必须谨慎对待因为不同发行版的默认权限有差异用A系统的修复规则去套B系统可能越修越乱。场景三定期安全审计每月或每季度做一次权限审计重点检查这些find / -perm -4000 2/dev/null # 检查所有setuid文件 find / -nouser -o -nogroup 2/dev/null # 查找无属主/属组的孤儿文件setuid文件清单你应该亲手过一遍确保没有不该出现的文件带着s位。孤儿文件往往来自卸载软件时删除用户但没删文件或是压缩包解压导致的uid错乱管理不善很容易被恶意利用。7. 实战经验三个值得记住的权限坑与最后补充最后聊几个我在实际工作中反复踩过的坑每个都是真金白银买来的教训。坑一用户主组不是你想的那个组用useradd创建用户时默认会创建一个与用户名同名的组并设为主组。如果你以为用户属于wheel组直接ls -l却没看到他创建的文件的属组是wheel大概率是因为你在添加用户到组之后没让他重新登录。组信息在登录时缓存添加组后必须重新登录或执行newgrp才能生效。一个简单验证id username看输出里的groups字段。坑二NFS和挂载盘上的uid/gid错位跨服务器挂载NFS时如果两台机器的uid/gid分配不一样A机器上uid1000的用户创建的目录在B机器上可能对应另一个完全不相关的用户。这就是为什么很多企业级环境都用LDAP统一管理用户uid或者用ACL配合Kerberos做认证。我在运维早期遇到过两台开发机A机的文件到B机后属主变成一个莫名其妙的用户查权限查了两小时才意识到是uid映射问题。所以涉及文件服务的跨机共享务必提前规划uid分配策略。坑三docker容器内外uid不一致在容器里跑应用容器内的rootuid0映射到宿主机上其实就是宿主机root。如果你在容器里以root身份挂载并写入了宿主机的目录宿主机上你会发现这些文件的属主变了权限变成了root拥有的文件普通用户根本动不了。社区方案是user_namespace重映射把容器内root映射成宿主机上普通用户的uid但配置复杂度不低。日常最简单的止血办法是容器内运行用户尽量指定非root例如--user 1000:1000并确保宿主机的目标目录属主与容器内uid对应。补充一个实用小技巧想快速知道某个用户对某个文件的实际权限可以用sudo -u username test -r file echo readable来验证读数用sudo -u username touch file来验证写权限。这种“以用户身份实测”的方法比纯看权限位更可靠。因为它把父目录权限、ACL、文件属性、挂载选项全都考虑进去了——权限判定是“多位一体”的你只看一个维度经常会被蒙。我自己运维多年下来最大的体会是Linux的权限体系不是给你添麻烦而是给你一个精确表达“谁能干什么”的语言。初学时觉得rwx九位字符太少完全无法覆盖复杂业务等用透了ACL、setuid、sudo、文件属性之后你会发现这套语言虽然老但极其可靠。它就像一把设计精良的机械锁只要你会用就几乎不会出现“钥匙断了”的情况。如果你也经常被权限问题折磨不妨把上面这套排查思路和实践命令存下来下次遇到Permission denied时照着走一遍绝对比盲目敲chmod 777靠谱得多。