资讯动态

Linux rwx 权限详解:文件与目录差异及排错实践

发布时间:2026/10/24 7:43:56 来源:尧图企业网站定制
Linux 权限这块命令本身没几个真正容易翻车的是把r、w、x在文件上的含义直接套到目录上。文件上r是能读内容、w是能改内容、x是能执行目录上完全不是这回事目录的r只管能不能列出名字x才决定能不能进去w决定能不能在里头新建和删除条目。很多“明明给了 777 还是报 Permission denied”“明明给了写权限还是删不掉文件”的奇怪问题根子都在这个区别上。这篇文章就围绕一个主题讲透rwx对文件和目录分别起什么作用。先把九个权限位和三类身份拆开再用一台普通 Linux 机器上就能复现的实验把“只有 r 没有 x”“只有 w 没有 x”“只有 x 没有 r”这几种反直觉组合跑一遍最后落到 Web 目录、团队共享目录、上传目录这几个真实场景该怎么配。看完你应该能做到两件事第一看到一个权限串就能反推出实际能干什么第二遇到权限报错能按路径逐级定位而不是上来就chmod -R 777。本文偏本地系统管理不涉及网络接口服务和 GPU 推理所以不会有 API 调用示例和显存占用章节。但权限修正本身经常是批量操作后面会给一套可以批量执行的检查和修正脚本这部分实践价值和批量任务是一回事。1. rwx 权限模型速览先把结论摆出来后面所有内容都是围绕这张表展开的。Linux 的权限位只有九个分成三组每组三个字符分别对应读、写、执行。关键在于同一组字符挂在文件上和在目录上语义完全不同。记忆的时候不要记成“r 就是读”要记成“r 在文件上是读内容在目录上是读目录项列表”这两件事在内核里走的是完全不同的代码路径。1.1 文件与目录的 rwx 对照表权限位对文件的作用对目录的作用典型命令缺了会怎样r读取文件内容列出目录内条目名称cat、less、grep、ls文件读不了目录ls报 Permission deniedw修改文件内容覆盖、追加、截断在目录内创建、删除、重命名条目echo 、vim 保存、touch、rm、mv文件写不进去目录内无法新建和删除x把文件当作程序执行进入目录、访问目录内已知道名字的条目./script.sh、cd、cat dir/file文件不能执行目录无法cd也无法访问内部文件组合要求脚本执行通常需要 r x创建和删除条目需要 w x-只给 w 不给 x目录基本废掉有一点必须提前说清楚文件的w权限不决定这个文件能不能被删除。删除一个文件本质是修改它所在目录的目录项所以判断依据是父目录有没有w和x跟文件自己是不是 444 没关系。这个结论很多人第一次听到会愣一下但它是理解整个权限模型的关键后面第 5 节会用实验把它验证出来。还有一个容易混的点是目录的r和x是解耦的。给目录r不给x你能看到目录里有哪些名字但拿不到这些名字对应的属性ls -l会显示一堆问号也进不去。给目录x不给r你进得去只要知道文件名就能访问但ls会直接被拒。这两种状态都不是“坏掉了”而是被刻意设计出来的能力边界。1.2 三类身份与九个权限位九个权限位按顺序分成三组分别对应文件属主owner简称 u、属组group简称 g、其他用户others简称 o。内核在做权限判定时是按“属主 → 属组 → 其他”的顺序匹配的一旦命中前一组就直接用那一组的结果不会再去比较后面的组。这个顺序带来一个很反直觉的后果如果一个文件属主是 alice属组是 dev权限是rwxr--r--那么 alice 就算属于 dev 组她拿到的也是属主那一组权限而不是两组取并集。这一点在排查“为什么同组的人权限比我大”这类问题时特别有用。正确做法是先id看当前用户属于哪些组再stat看文件的属主和属组分别是谁最后按顺序推一遍命中哪一组而不是凭感觉猜。# 查看当前用户身份与所属组 id # 输出示例uid1000(alice) gid1000(alice) groups1000(alice),1001(dev) # 查看文件属主、属组与完整权限 stat /srv/app/config.yamlstat的输出比ls -l更完整它会直接把八进制权限和符号权限同时列出来还会给出三个时间戳。排查权限问题时stat应该是第一个敲的命令因为ls -l在目录缺x的情况下可能连属性都读不全。2. 从 ls -l 输出读懂权限位实际工作中绝大多数人是从ls -l开始接触权限的但很多人只是记住了“rwx 分别是读写执行”没注意开头那个字符。开头字符决定了后面九个位的解释方式-是普通文件d是目录l是符号链接c是字符设备b是块设备s是套接字p是管道。同一个rwx串前面是-还是d含义就分叉了。2.1 逐位拆解一个真实输出ls -l /srv/app # -rwxr-x--- 1 deploy deploy 20480 Mar 12 10:21 start.sh # drwxr-x--- 3 deploy deploy 4096 Mar 12 10:21 logs第一行-rwxr-x---第一位是-说明是普通文件。接下来三位rwx是属主权限属主 deploy 能读、能写、能执行。再三位r-x是属组权限deploy 组成员能读、不能写、能执行。最后三位---是其他用户权限什么都不能干。这个文件对除属主和属组以外的人是完全封闭的。第二行drwxr-x---第一位是d说明是目录。同样三段属主 deploy 有rwx属组 deploy 组有r-x其他人什么都没有。注意这里的w不是“能修改 logs 目录里的文件内容”而是“能在 logs 目录里新建、删除、重命名条目”。属组只有r-x意味着组成员能进来、能看见有哪些日志文件、能读日志但删不掉也建不了新的。再往后两列是硬链接数和属主属组然后才是大小和时间。目录的“大小”通常显示为 4096这是目录项本身占用的块大小不是里面文件的总和不要拿它做容量判断。目录的实际内容大小要用du -sh看。2.2 数字表示法与符号表示法权限有两种写法八进制数字和符号。八进制把rwx分别记为 4、2、1三位相加得到 0 到 7三组拼起来就是三位八进制数。rwxr-x---就是750因为属主 4217属组 4015其他 0000。符号写法用u、g、o、a加、-、来描述增减chmod g-w表示把属组的写权限去掉。八进制符号含义7rwx读、写、执行全给6rw-读、写不能执行5r-x读、执行不能写4r--只读3-wx写、执行不能读2-w-只写1--x只执行0---全无数字写法的优点是短缺点是可读性差而且chmod -R 777这种图省事的操作一旦敲下去很难在事后看出原本想表达什么。符号写法更适合精确增减比如“只给属组加写权限”就写chmod gw file不会动到其他位。工程上更推荐符号写法尤其是在脚本里因为它不会误伤没提到的位。3. rwx 对文件的作用文件上的rwx是最符合直觉的一组但每一层都有细节。r控制能不能打开文件读取内容w控制能不能修改内容x控制能不能作为程序被加载执行。三者相互独立只是不同操作会同时依赖多个位。3.1 r读取文件内容只有具备r权限才能用cat、less、grep、head这类命令读取文件内容。这里说的“读”是指打开文件并读取数据不包括查看元数据。文件的元数据大小、属主、时间戳由它所在目录的x权限控制只要你能进入目录就能stat到一个你完全读不了内容的文件这是正常行为不是漏洞。一个常被忽略的点是w权限本身就隐含了部分读的能力。如果你对一个文件只有w没有r虽然不能正常读取但在很多场景下可以用vim打开、保存甚至通过截断覆盖的方式间接影响内容。所以从安全角度讲“只给写不给读”并不是一个可靠的隔离手段真正需要隔离时应该直接不给w。3.2 w修改文件内容但不等于能删除w权限允许修改文件内容包括追加、覆盖、截断。用echo x file追加需要w用vim保存需要w用重定向覆盖也需要w。但注意w只作用于“通过这个文件路径去写数据”这个动作。删除文件走的是另一条路。rm file实际做的是在父目录里删掉那个目录项内核检查的是父目录的w和x跟文件本身的权限位没有关系。所以你会看到一个文件权限是444属主却依然能把它删掉只要父目录允许。反过来父目录不允许写文件权限给到777也删不掉rm会直接提示权限不足。这个特性在设计共享目录时非常关键。如果你希望“大家都能往里放文件但只能删自己的”光靠文件权限做不到必须用目录的粘滞位sticky bit。/tmp就是这么配的权限是1777所有人都能建文件但只有属主能删自己的文件。3.3 x把文件当作程序执行x权限决定文件能不能被内核当作程序加载。对二进制可执行文件来说只要有x就能跑不需要r。对 Shell、Python 这类脚本来说除了x还需要r因为解释器要先读取脚本内容才能执行如果只有x没有r会报Permission denied或者bad interpreter之类的错误。x权限在文件上还有一个特殊之处新建的普通文件默认不带x这是有意的设计防止下载下来的东西直接被执行。想执行必须先显式chmod x这个动作相当于一次人工确认。生产环境里应该保持这个习惯不要用umask 000之类的方式让新文件默认带执行位。3.4 一个完整的权限判定流程把文件的权限判定串起来看大致是这样一条链路先根据进程的有效用户身份和文件属主、属组做匹配命中哪一组就用哪一组的三位权限然后看具体操作需要哪些位。读内容要r写内容要w执行二进制要x执行脚本要r x。任何一位不满足对应的系统调用就返回EACCES。# 创建一个脚本并观察权限变化 echo echo hello /tmp/demo.sh ls -l /tmp/demo.sh # -rw-r--r-- 1 alice alice 12 Mar 12 10:30 /tmp/demo.sh /tmp/demo.sh # bash: /tmp/demo.sh: Permission denied chmod ux /tmp/demo.sh ls -l /tmp/demo.sh # -rwxr--r-- 1 alice alice 12 Mar 12 10:30 /tmp/demo.sh /tmp/demo.sh # hello这段演示说明两件事新建文件默认没有执行位加上之后才能直接运行。另外如果你换成chmod go-r把读权限去掉只留执行位脚本就会执行失败而同样操作的二进制程序依然能跑。这就是“脚本需要 r x”的具体表现。4. rwx 对目录的作用这一节是全文的重点。目录在 Linux 里是一个特殊文件它的内容是一张表表里每一行记录着“文件名到 inode 编号”的映射。r、w、x三位分别作用在这张表的不同操作上理解了这个数据结构三种权限的行为就都能推出来不需要死记。4.1 r列出目录内容目录的r权限允许读取目录项列表也就是执行ls拿到里面有哪些名字。注意这里只给名字不给属性。想看到每个文件的权限、大小、时间戳内核还得对每个名字做一次stat而这一步需要目录的x权限。这就解释了一个经典现象一个目录权限是r--ls能列出文件名但ls -l会显示一堆?????????同时在 stderr 打出一串Permission denied。很多人看到问号以为是文件系统坏了其实只是缺x内核拿不到那些条目的 inode 信息。r权限对安全的意义比想象中大。只有x没有r的目录虽然外面的人进不来也列不出名字但如果对方通过其他途径知道了确切文件名依然可以直接访问。所以“隐藏文件名”不能当作安全手段真正的隔离要靠x位和更上层的目录权限。4.2 x进入目录与访问内部条目目录的x权限是“通行权”它允许你把这个目录作为路径中的一环穿过去也允许你对目录内已知名字的条目做操作。cd进目录需要xcat dir/file需要路径上每一级目录都有x甚至stat dir/file也需要。这个特性带来的最重要结论是权限检查是逐级进行的路径上任何一级目录缺x后面所有操作都会失败哪怕最终目标文件的权限是777。这就是为什么排查权限问题必须从根开始逐级往下看而不是只盯最后一个文件。# 逐级检查路径上每一层目录的权限 namei -l /srv/app/logs/app.log # f: /srv/app/logs/app.log # drwxr-xr-x root root / # drwxr-xr-x root root srv # drwxr-x--- deploy deploy app # drwxr-x--- deploy deploy logs # -rw-r----- deploy deploy app.lognamei -l是排查多级路径权限最省事的工具它会把路径上每一层目录的权限串行列出来一眼就能看出是哪一级断了。比起一级一级ls -ld敲过去效率高很多建议直接记住。4.3 w创建、删除、重命名目录项目录的w权限允许修改目录项列表对应三个操作新建条目touch、mkdir、cp进来、删除条目rm、rmdir、重命名条目mv在同目录内改名。这三个动作本质都是改那张映射表。关键在于光有w不够还需要x。因为新建一个文件时内核要先在目录里查找这个名字是否已存在这个查找动作需要遍历权限。所以-w-这种权限组合在实际使用中几乎等于没有touch会直接失败。真正可用的“可写目录”至少是-wx常见配置是rwx或者rwx配合粘滞位。删除也是同理。rm dir/file需要dir的w和x不需要file的任何权限。如果dir上还设置了粘滞位那么还额外要求当前用户是文件属主、目录属主或者 root。这三条限制叠在一起才是/tmp那种“谁都能放、只能删自己的”效果。4.4 为什么 r 和 x 要解耦有人会问既然目录的r和x几乎总是一起给为什么内核要设计成两个独立的位。原因是有真实场景需要它们分开。最典型的是“投递目录”允许外部程序往目录里写文件但不允许它们看到目录里还有别的什么文件。这种场景下目录给-wx不给r程序知道确切路径就能写入但列不出目录内容看不到其他文件的名字。另一个场景是“只读穿透目录”给--x不给r使用者只要知道确切的文件路径就能访问但无法浏览。Web 服务器的一些静态资源目录就采用类似思路把目录列表关掉只允许按 URL 精确访问。这两种用法都说明r和x的分离不是历史包袱而是有意留出的能力。5. 五种组合的实验验证光看结论印象不深这一节给一套可以在一台普通 Linux 机器上直接跑完的实验。整个过程只用到/tmp下的临时目录不需要 root也不会影响系统其他部分。跑完之后目录rwx的各种组合行为应该就变成肌肉记忆了。5.1 实验准备# 建立实验目录当前用户即可不需要 root mkdir -p /tmp/perm-lab cd /tmp/perm-lab mkdir target echo hello permission target/inner.txt ls -ld target # drwxr-xr-x 2 alice alice 4096 Mar 12 11:00 target实验用两个终端最方便。一个终端保持当前用户身份另一个终端su成另一个普通用户比如testuser用来验证“其他人”这一组的权限效果。如果只有一个账号也可以临时把属主改成 root自己以普通用户身份去访问效果一样。5.2 目录权限组合测试# 只给 r不给 x chmod 400 target ls target # 能列出 inner.txt ls -l target # ls: cannot access target/inner.txt: Permission denied # 同时看到 ????????? 的属性 cd target # bash: cd: target: Permission denied cat target/inner.txt # cat: target/inner.txt: Permission denied这组结果说明r只负责“列名字”一旦涉及访问具体条目就必须要x。ls -l和cd和cat全部失败就是因为它们都需要穿透目录。# 只给 x不给 r chmod 100 target ls target # ls: cannot open directory target: Permission denied cd target # 成功进入 pwd # /tmp/perm-lab/target cat /tmp/perm-lab/target/inner.txt # hello permission这组结果更能说明问题目录列不出来但只要能说出确切路径文件照样能读。这就是“只读穿透”的实际效果。很多“目录明明看不见却能访问”的疑问到这里应该就有答案了。# 只给 w不给 x 和 r chmod 200 target touch target/new.txt # touch: cannot touch target/new.txt: Permission denied rm target/inner.txt # rm: cannot remove target/inner.txt: Permission denied这组是重点中的重点。只有w的目录什么都干不了因为创建和删除都需要先遍历目录x再改目录项w。所以chmod 200在实践中没有任何可用价值别以为给了写权限就能往里塞文件。# 给 w x不给 r chmod 300 target touch target/new.txt # 成功创建 ls target # ls: cannot open directory target: Permission denied rm target/new.txt # 成功删除这就是前面说的“投递目录”效果能写能删但看不见目录里有什么。如果你在配上传目录这就是想要的状态之一只是要注意删除能力也一并给出来了需要配合粘滞位限制。5.3 文件删除与文件权限的分离验证接下来验证“删除看目录不看文件”这个结论。# 恢复目录可读写把文件设成只读 chmod 755 target chmod 444 target/inner.txt ls -l target/inner.txt # -r--r--r-- 1 alice alice 16 Mar 12 11:05 target/inner.txt # 文件只读但父目录可写照样能删 rm target/inner.txt # 删除成功 # 反过来文件 777父目录不可写 echo test target/inner2.txt chmod 777 target/inner2.txt chmod 555 target rm target/inner2.txt # rm: cannot remove target/inner2.txt: Permission denied这两组结果把结论钉死了删除权限跟文件自己的权限位完全无关只看父目录有没有w和x。理解这一条之后你就能解释为什么“文件加了只读还是被删了”以及“文件权限全开还是删不掉”这两类问题。5.4 粘滞位的效果# 给目录加上粘滞位 chmod 1777 target ls -ld target # drwxrwxrwt 2 alice alice 4096 Mar 12 11:10 target # 用另一个普通用户 testuser 尝试删除 alice 的文件 echo alice file target/alice.txt su - testuser rm /tmp/perm-lab/target/alice.txt # rm: cannot remove /tmp/perm-lab/target/alice.txt: Operation not permitted粘滞位只在目录上生效作用是“即使是可写目录也只能删除属于自己的条目”。/tmp的1777就是标准配置。团队共享目录如果出现“误删别人文件”的事故加这一位通常是最直接的修复手段。6. 典型场景的权限设计理论讲完落到实际。这一节挑四个运维里最常遇到的目录场景给出可以直接套用的配置。每个配置后面都会说明为什么这么配以及配错会出什么问题。6.1 Web 站点目录Web 站点的权限配置是重灾区。常见错误是把整个站点目录设为777理由是“不然上传不了”。正确的做法是把“代码目录”和“上传目录”分开代码目录只读上传目录单独放开。# 代码目录属主可写Web 服务只读 chown -R root:www-data /var/www/html find /var/www/html -type d -exec chmod 755 {} \; find /var/www/html -type f -exec chmod 644 {} \; # 上传目录Web 服务可写但不能执行脚本 mkdir -p /var/www/html/uploads chown -R www-data:www-data /var/www/html/uploads chmod 755 /var/www/html/uploads上传目录最关键的一条是“不能执行”。如果 Web 服务进程对上传目录有rwx恶意上传的脚本就可能被直接请求执行。稳妥做法是让 Web 服务器对上传目录单独配置禁止执行脚本只允许静态访问。权限层面能做的辅助手段是不给执行位但这只能防住一部分真正可靠还是靠服务器配置。另外注意find -exec chmod这种写法会逐个文件调用chmod文件多的时候很慢。可以换成find /var/www/html -type d -print0 | xargs -0 chmod 755或者用chmod -R分两步配合find更精确。批量修正权限时一定要先-print看一遍结果再执行避免手滑。6.2 团队共享目录共享目录的需求通常是“组内成员都能读写其他人不能进谁也别删别人的文件”。这个需求需要三个权限位配合目录的rwx给组、粘滞位防误删、SGID 让新文件继承组。# 创建共享目录 mkdir -p /srv/share chown root:dev /srv/share # 目录属主和组可读写进入其他人无权限 chmod 2770 /srv/share ls -ld /srv/share # drwxrws--- 2 root dev 4096 Mar 12 11:20 /srv/share2770里的2是 SGID。SGID 作用在目录上时会强制新建的文件和子目录继承父目录的属组而不是创建者的主组。没有这一位组内每个人的主组可能不同新建的文件属组会五花八门其他人就访问不了。这是共享目录能不能真正用起来的分水岭。如果还需要防止组内成员互相删文件把粘滞位也加上权限变成3770。不过要注意粘滞位会让“组内协作修改同一个文件”变得麻烦具体加不加要看业务是不是真的需要互相覆盖。权限设计永远是在便利和隔离之间取平衡没有一套配置能通吃所有场景。6.3 上传与投递目录投递目录的诉求是“外部程序能写进来但看不到目录里有什么”。这就是第 4 节讲的-wx组合。mkdir -p /srv/inbox chown root:app /srv/inbox chmod 733 /srv/inbox ls -ld /srv/inbox # drwx-wx-wx 2 root app 4096 Mar 12 11:25 /srv/inbox733表示属主rwx属组-wx其他-wx。app 组的进程可以往里面写文件、删自己的文件但ls会失败。这个配置的实际价值在于阻断“先列目录再挑文件”的攻击路径让外部程序只能按约定好的文件名操作。这类目录通常还要配合应用层的文件名规范比如要求文件名带时间戳和随机串避免重名覆盖。权限只能控制“能不能写”控制不了“写什么”两层要一起做。6.4 家目录的 755 与 700家目录的默认权限在不同发行版上不太一样有的是700有的是750也有配成755的。从安全角度讲700是最稳妥的因为家目录里经常放 SSH 私钥、配置文件、浏览记录这类东西。755意味着同机器上任何用户都能列目录、能读到没额外保护的配置文件。# 收紧家目录权限 chmod 700 /home/alice ls -ld /home/alice # drwx------ 2 alice alice 4096 Mar 12 11:30 /home/alice # SSH 目录和密钥文件的推荐权限 chmod 700 /home/alice/.ssh chmod 600 /home/alice/.ssh/authorized_keys.ssh目录和密钥文件的权限是 SSH 服务强制检查的权限过宽会直接拒绝登录报Authentication refused: bad ownership or modes。这也是权限问题里少数会明确报错并指出原因的场景遇到了按提示改就行不用猜。7. 权限修改命令与 umask命令本身不复杂难点在于选对范围和选对时机。chmod改权限chown改属主属组chgrp只改属组umask控制新建文件的默认权限。四个命令各有各的坑这一节逐个说。7.1 chmod 的符号与递归# 常用写法 chmod 644 /var/www/html/index.html chmod ux deploy.sh chmod gw,o-rwx /srv/share/config # 递归修改要分类型处理不要一把梭 find /srv/app -type d -exec chmod 755 {} \; find /srv/app -type f -exec chmod 644 {} \;递归修改最大的坑是chmod -R 777 dir。这一条会把目录和文件全部设成完全开放目录变成“谁都能进能删”文件变成“谁都能改能执行”安全边界直接归零。更麻烦的是这种修改很难回滚因为原始权限没有备份。如果确实要批量改先记录一份现状。# 修改前先备份权限清单 find /srv/app -printf %m %u %g %p\n /root/perm-backup-$(date %F).txt # 出问题时可以照着恢复 # 逐行读取并用 chmod/chown 还原-printf是 GNU find 的扩展不是所有系统都支持。在不支持的环境里可以用stat -c %a %U %G %n配合find -exec达到类似效果。备份权限清单这个习惯在做过一次事故之后就会养成成本很低收益很高。7.2 chown 的属主与属组# 只改属主 chown alice file.txt # 只改属组 chown :dev file.txt chgrp dev file.txt # 同时改 chown alice:dev file.txt # 递归修改 chown -R www-data:www-data /var/www/html/uploads改属主需要 root 或者 CAP_CHOWN 能力普通用户不能把自己的文件送给别人。改属组相对宽松文件属主可以把属组改成自己所属的组。这个差异在做共享目录时要注意普通用户自己能解决属组问题改属主必须找管理员。另外要注意改属主之后文件的 SUID 和 SGID 位会被清掉这是内核的安全设计防止有人通过改属主继承特权。如果你确实需要保留这些位改完属主要重新chmod一次。7.3 umask 与默认权限新建文件不会直接给777实际权限等于“基础权限减去 umask”。普通文件基础权限是666目录是777所以umask 022下新建文件是644新建目录是755。这个减法按位做不是算术相减。# 查看当前 umask umask # 0022 # 临时调整 umask 077 # 永久生效写进 shell 配置 echo umask 077 ~/.bashrcumask 077的效果是新建文件和目录只有自己可访问适合个人开发机和服务器上的敏感目录。但要注意它影响的是整个 shell 会话里所有新建文件如果在这个会话里跑构建脚本产出的文件其他服务可能读不了会出现“构建成功但服务起不来”的怪问题。7.4 特殊权限位简述rwx之外还有三位SUID4、SGID2、Sticky1。SUID 作用在可执行文件上让执行者临时获得文件属主的权限/usr/bin/passwd就是典型例子。SGID 在文件上类似在目录上则是强制继承属组。Sticky 只对目录有意义前面已经讲过。# 查找系统中的 SUID 文件定期审计 find / -xdev -perm -4000 -type f 2/dev/null # 查找全局可写的目录 find / -xdev -type d -perm -0002 2/dev/null这两条命令是安全巡检的常用项。SUID 文件多了意味着攻击面大全局可写目录多了意味着有被植入文件的风险。定期跑一遍跟基线对比出现异常变化就值得查一下。8. 权限审计与定位方法权限问题排查有一套固定套路先确认当前身份再确认路径上每一级目录的权限再确认目标文件的权限最后确认是不是被 ACL、SELinux、AppArmor 这类上层机制拦住。按这个顺序走绝大多数问题五分钟内能定位。8.1 用 stat 和 namei 快速定位# 确认身份 id groups # 确认路径上每一级 namei -l /srv/app/logs/app.log # 确认目标文件完整信息 stat /srv/app/logs/app.lognamei -l的价值前面提过这里再强调一次它是唯一能一次性把整条路径权限列出来的标准工具。遇到跨多级目录的权限问题时第一条命令就应该是它而不是逐个ls -ld。8.2 用 find 批量审计# 找出组或其他用户可写的目录 find /srv -type d \( -perm -0020 -o -perm -0002 \) 2/dev/null # 找出没有执行位的目录会导致无法进入 find /srv -type d ! -perm -0111 2/dev/null # 找出权限为 777 的文件和目录 find /srv \( -type f -o -type d \) -perm 777 2/dev/null-perm后面不带减号是精确匹配带减号是“至少包含这些位”。这两个语义差别很大写的时候要看清楚。-perm -0002表示“其他人位里包含写权限”能抓到666、777、722这些-perm 777只抓777。批量审计的结果通常要导出成文件跟预期基线做 diff。手工一条条看效率太低而且容易漏。写个定时任务每天跑一次输出存到固定目录出了问题翻历史记录比现场猜可靠性高得多。8.3 权限检查的性能开销权限检查本身是内核路径解析的一部分单次开销极小但在大规模文件操作时会累积。典型的表现是一个目录里有几十万个文件ls -l要几秒甚至几十秒。原因不是磁盘慢而是ls -l要对每个条目做一次stat每次stat都要走路径解析和权限检查条目数一多耗时线性增长。优化思路有几条。第一少用ls -l这种带属性的列目录方式只需要名字时用ls -1或者find -maxdepth 1。第二批量处理用find -print0 | xargs -0减少进程创建次数。第三超大目录考虑按时间或哈希分桶单目录条目数控制在万级以内。9. 常见问题与排查方法下面这张表覆盖了日常最常遇到的权限类报错按现象、原因、排查、解决四列组织。遇到问题时先按现象找到对应行再去验证原因不要一上来就改权限。问题现象可能原因排查方式解决方案ls能列出名字但ls -l全是问号目录有r无xnamei -l看该级目录权限给目录补x如chmod ox dircd提示 Permission denied目标目录缺xls -ld确认三位权限给需要的身份补x文件是 444 却能被删掉删除只看父目录wxls -ld看父目录正常行为需要限制就用粘滞位文件 777 却删不掉父目录缺w或x检查父目录权限给父目录补权限或换有权限的用户脚本提示 Permission denied缺执行位或缺读位ls -l看文件权限chmod ux file脚本还要保证可读保存文件提示只读文件缺wstat看权限chmod uw file上传文件失败目标目录缺w或x检查目录权限和属主给运行进程的用户补wx组内成员互相改不了文件文件属组不对或目录缺 SGIDls -l看属组ls -ld看目录目录加 SGID统一属组互相误删文件共享目录没有隔离检查目录权限加粘滞位chmod t dirSSH 登录被拒.ssh或密钥权限过宽看/var/log/auth.logchmod 700 .sshchmod 600 authorized_keys批量改完权限服务起不来chmod -R把目录执行位去掉了检查目录权限目录统一755文件统一644分开处理权限看起来都对还是失败ACL、SELinux、挂载选项getfacl、ls -Z、mount按上层机制单独处理清理一下几个容易被误判的场景。第一种是挂载选项比如noexec挂载的分区上文件权限里有x也执行不了这种情况权限位完全正确但操作失败要从mount输出里找原因。第二种是 ACLgetfacl能看到额外的授权条目ls -l看不出来只在权限串末尾显示一个号。第三种是 SELinuxls -Z看安全上下文/var/log/audit/audit.log里会有拒绝记录。还有一种很隐蔽的情况是进程能力capabilities。某些程序以非 root 身份运行但被赋予了特定的 capability能绕过常规权限检查。这类问题用getcap查普通权限分析工具看不出来。遇到“权限明明不对但就是能跑”的诡异现象时可以往这个方向想一下。10. 最小权限落地建议权限配置的核心原则只有一条只给完成工作所必需的最小权限多一位都不给。这条原则说起来简单执行起来需要克制。很多事故的起因不是有人恶意操作而是图省事把权限放大之后忘了收回来。第一条建议是区分文件和目录批量处理。目录需要x才能进入文件通常不需要执行位所以统一chmod -R 755是错的它会给所有文件加上执行位。正确做法是目录755、文件644分开设用find -type d和find -type f各处理一遍。第二条建议是属主和权限分离管理。属主决定“归谁”权限决定“谁能干什么”。改属主用chown改权限用chmod两个动作分开做日志清晰出问题好回溯。混在一起写容易在一次操作里改错两样东西。第三条建议是给关键目录建立权限基线并定期比对。基线可以用前面给的find -printf导出存成带日期的快照。发生变化时对比差异能快速发现“谁在什么时候把某个目录放开了”。这个机制在多人共管的服务器上尤其必要。第四条建议是涉及用户上传、第三方素材、外部数据的目录一律不给执行位并且单独挂载或者单独配置服务端禁止脚本执行。权限位只能防住一部分应用层和服务器层的限制要一起上。第五条建议是遇到权限问题先读日志再动手。/var/log/auth.log、/var/log/secure、应用的错误日志里通常有明确的EACCES记录和路径信息比凭感觉猜快得多。改权限之前先把现状备份一份改完验证通过再清理备份这个顺序能救回很多次误操作。最后补一个实操技巧不确定某个权限组合的实际效果时与其查文档不如在/tmp下建个临时目录跑一遍。前面第 5 节那套实验五分钟能跑完跑完得到的结论比任何记忆都可靠。权限这件事动手验证一次胜过背十遍表。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑