1. “问题不大权限不够”从一次登录失败说起有段时间我养成了一个坏习惯——在公司内部某台共享服务器上图省事把所有要修改的文件都chmod 777。后来一次例行安全扫描发现某目录下多了一个不属于任何人的可执行文件被标记为“危险操作来源”。排查之后我才意识到权限不等于摆设Linux 下的一切安全问题归根结底都是权限问题。组里一个新人接手环境时连自己的用户目录都进不去因为他把.config目录的权限写得乱七八糟把自己锁在了外面。那会儿我才认认真真把 Linux 权限相关的指令从头过了一遍。这篇文章就是基于那段“交学费”的经验写的不搞教科书式的通篇铺陈只讲我在实际服务器上每天都会碰到的几条命令以及它们背后容易被人忽略的细节。无论你是刚开始摸服务器的小白还是已经被权限问题折磨过的老手这几条指令都值得重新对照一遍。2. 权限模型别急着敲命令先搞懂“谁”和“能做什么”2.1 三类主体和三种权限位Linux 的权限模型可以用一句话概括系统对“用户/用户组/其他人”这三种主体分别赋予“读/写/执行”三种操作能力。在命令行里输入ls -l能看到类似-rw-r--r--的输出这串字符就是权限的“压缩密码”。从左往右拆第 1 位是文件类型-普通文件d目录l软链接第 2-4 位是属主uuser权限第 5-7 位是属组ggroup权限第 8-10 位是其他人oother权限后面跟的数字代表硬链接数再后面是属主、属组、大小、修改时间和文件名。权限本身也是三位一组r代表读4 分、w代表写2 分、x代表执行1 分。为什么很多人直接写755、644因为八进制数字就是把每组的三个 rwx 换成数值相加。例如rwxr-xr-x属主是 4217属组是 4015其他也是 5于是简写为755。这里有一个容易踩的坑目录的 r、w、x 和文件的含义不完全一样。对目录来说r只能让你“看到”目录里有哪些文件名w允许你在目录里新建、删除、重命名文件x才是真正允许你“进入”这个目录并访问其中文件的能力。所以一个目录如果只有r没有x用ls能看到文件名但cd进去会提示权限不够访问其中任何文件也会失败。反过来只有x没有r你能进去但看不到有哪些文件只能凭完整路径访问已知文件。给目录设置权限时通常建议r和x成对出现否则极易出现“看得到进不去”或者“进得去看不到”的诡异现象。2.2 ls 输出里的隐藏线索除了这十个字符ls -l还会暴露一些容易被忽略的线索如果权限位后面跟着一个.表示该文件启用了 SELinux 上下文如果跟着表示该文件上设置了扩展 ACL 规则后面会讲到如果属主或属组显示为一个数字而不是名字说明系统里找不到对应的用户记录通常是残留文件或者容器场景下常见。实操时我一般会在ls -l基础上加-h把文件大小变成人类可读的 K/M/G 格式加--time-stylelong-iso让时间输出成2025-06-12 18:30:01这种标准格式日志排查时按时间排序特别好用。ls -ld则用来查看目录自身权限而不是目录里面的内容检查 /tmp、/var/log 这类“不友好目录”时很关键。提示ll在很多发行版里是ls -l的别名但某些精简环境里没有定义养成直接敲ls -l的习惯到哪都不会抓瞎。2.3 为什么要用“组”而不是直接给每个人授权权限设计里最常用到的其实是“组”。一台服务器上可能有开发、运维、数据分析三个角色如果给每个人单独分配权限管理成本会指数级上升。正确做法是把某类需要相同权限的人放进同一个组然后针对“组”设置权限之后人员变动只需要把用户加进/移出组文件的权限位完全不用动。这是多数团队服务器的标准做法也是应对审计需要的基础设计。3. 修改文件权限chmod、chown 与 chgrp 的完整实操3.1 chmod 的两种模式字母模式和数字模式chmod是用来改权限位的主命令写法有两种流派符号模式字母和数字模式八进制。两者没有绝对优劣但混用时容易出错建议团队内部统一风格。符号模式适合精确调整某一位。比如chmod ux file.sh给属主加执行权限chmod g-w file.txt去掉属组的写权限chmod or file.txt把其他人的权限“设置”为只读注意是等号不是加减号chmod ar file.txt所有人all都加上读权限。数字模式则适合直接“覆盖设定”例如chmod 644 file.txt表示属主可读写其他人只读chmod 755 script.sh表示属主可读写执行其他人和属组仅可读执行。最常见的几个组合建议直接背下来644普通文件属主读写别人只读配置文件常用755可执行文件/目录属主全权其他人可读可进入700私有文件/目录只有属主能进能改600敏感文件比如私钥、凭据只有属主能读写4755或4754带 setuid 的特殊组合下文会细讲。新手最容易犯的第一个错误是对目录递归用了chmod -R 777。-R的意思是递归会把目录下所有文件和子目录全部改一遍。看似一劳永逸实际上把“是否需要执行权限”这种本该由文件性质决定的事情一刀切了。更稳妥的做法是分两步先用find /path -type f -exec chmod 644 {} \;给普通文件设权限再用find /path -type d -exec chmod 755 {} \;给目录设权限。这样目录保留了 x 权限可进入普通文件不会被误加执行位。3.2 chown 与 chgrp改属主和属组的边界chown用于修改文件的属主和属组。常见写法chown alice file.txt仅改属主chown alice:devs file.txt同时改属主为 alice、属组为 devschown :devs file.txt只改属组前面的属主用冒号占位chown -R alice:devs /data/project递归修改整个目录树。chgrp则是单独修改属组的命令虽然chown :devs file.txt也能达到同样效果但老派运维习惯用chgrp因为可读性更好也避免手滑把属主改错。这里必须提醒一条原则chown只有 root 能执行。普通用户不能把自己的文件“送”给别人也不能把别人的文件“抢”过来这是系统防越权的基本设计。如果你遇到“Operation not permitted”提示先确认自己有没有sudo权限而不是反复试命令。3.3 实操场景部署一套 Web 服务的权限规划举个例子我要在一台新服务器上部署一个静态站点站点根目录在/var/www/htmlWeb 进程以www-data用户运行。合理的权限规划流程是创建组webteam把负责维护的管理员账号加入该组把网站目录属主设为www-data属组设为webteam目录权限设为750属主web 进程可读写进入组内成员可读进入其他人都被拒之门外文件权限设为640属主可读写组内成员可读其他人无权限唯一可能需要写的目录比如上传目录uploads/单独设为www-data:webteam且权限770保证只有进程和组内成员能写。整个过程中用到的是chown -R www-data:webteam /var/www/html再配合chmod逐个目录设置。这个做法比chmod -R 777复杂一些但避免了网站被任意系统用户篡改的风险排查问题的时候也能一眼看出哪个目录权限不合理。注意chown修改完属主属组后建议立刻用ls -l复查一遍因为有些发行版会自动把属主的组改为用户主组例如用户 alice 的主组是 alice则chown alice file会把属组一并改成 alice这就很容易导致原本期望的“组内共享”变成“只有单人能访问”。4. 用户与组管理权限分配的下层基础4.1 用户管理指令useradd 与 usermod权限的主体是用户。日常维护中useradd、usermod、userdel这三条命令值得一提。useradd创建用户时参数极其重要因为不同发行版对新用户的默认设置不一样。我常用的完整写法是useradd -m -s /bin/bash -G devs,wheel -c 某开发者 alice-m创建用户主目录不加的话可能没有/home/alice目录许多新人因此踩坑-s指定 shell如果设置成/bin/bash就按 bash 环境处理-G附加组用户会加入这些次要组注意和主组不是一回事-c备注信息一般写姓名或用途方便后续识别。usermod是在用户创建之后修改信息的。最常见的操作是追加组usermod -aG devs alice。这里必须强调-aappend几乎要作为固定搭档使用。如果不加-a-G会把用户从其他所有附加组里移除相当于重置了用户的所有附加组权限。我见过有人想给某同事临时加一个 docker 组结果顺手把人家从十几个项目组里全踢出来了第二天十几个项目同时报“权限不足”。删除用户的命令是userdel -r alice-r会连带删除用户主目录和邮件池。如果用户的主目录下有重要业务数据务必确认备份后再执行没有-r时用户删除了但主目录还在有时会留下孤儿目录属主和属组都显示为数字后续清理很麻烦。4.2 组管理groupadd 与 gpasswd组操作相对简单groupadd devs gpasswd -a alice devs # 把用户加入组 gpasswd -d alice devs # 从组中移除gpasswd比直接改/etc/group文件安全因为后者如果编辑中途格式错误可能导致整个系统登录异常。组修改还有一个容易被忽略的规则用户加入新组之后必须重新登录或重新开启一个会话才会生效因为登录时获得的组列表不会动态刷新。如果你看到明明加进了 docker 组执行 docker 命令还是提示权限不足先执行id或者groups看输出里有没有 docker没有就是会话没刷新重新登录即可。4.3 passwd 与密码策略的简单维护passwd也是权限相关指令里不可跳过的一条。普通用户运行passwd只能改自己的密码root 运行passwd alice可以强制重设别人的密码也可以直接锁定/解锁账户-l/-u。针对弱密码账户建议在团队里约定密码至少 12 位包含大小写、数字和符号并定期轮换。虽然passwd不能直接强制用户改密码但 root 可以用chage -d 0 alice强制用户下次登录时立刻改密码这在临时创建临时账号时很实用。5. 特殊权限位与访问控制扩展从 777 的误区里跳出来5.1 setuid、setgid 与粘滞位隐藏在常规权限之外的三种特殊权限普通权限位之外Linux 还提供三套“特殊权限”对应的数值分别是 4setuid、2setgid、1粘滞位sticky bit。它们平时不显眼但一旦用错就是安全漏洞的温床。setuid权限位表现为属主的 x 变成 s 或 S命令以属主而不是执行者的身份运行。经典例子是/usr/bin/passwd它的属主是 root普通用户执行它时能临时获得 root 权限去修改/etc/shadow文件但又不直接把 root 交给用户。这个设计很精妙但自定义脚本设置 setuid 极其危险因为如果脚本本身有漏洞等于是把 root 的钥匙挂在门口。setgid属组 x 变成 s 或 S文件执行时以属组身份运行如果设置在目录上则该目录下新建的文件和子目录默认继承目录的属组而不是创建者自己的主组。这一点非常适合团队共享目录——在共享目录上执行chmod gs /data/shared后无论谁往里面放文件文件属组都是项目组不会因为创建者属于不同用户组而导致其他成员无法访问。粘滞位目录权限最后一位的 x 变成 t 或 T最常见于/tmp目录。设置了粘滞位的目录里所有人都能创建文件但只有文件属主或 root才能删除别人的文件。这样避免了“公共垃圾桶里互相扔东西”的问题。设置方法chmod us /path/to/file chmod gs /path/to/dir chmod t /path/to/dir或数字模式chmod 4755 /path/to/file chmod 2770 /path/to/dir chmod 1777 /tmp注意数字模式下特殊权限位放在普通权限位之前四位数字比如4755表示 setuid 7551777表示粘滞位 7772770表示 setgid 770。检查时用ls -l看 x 位是否被 s/t 替代如果显示大写 S 或 T说明特殊权限位没生效或者该位本身没有执行权限这实际上是一个异常状态需要排查。5.2 扩展 ACL比 chmod 更细粒度的“定向授权”有些场景下chmod 的三种主体属主、属组、其他人不够用。比如同一份文档目录里alice 需要读写权限bob 只需要读权限其他人一律不可访问。用 chmod 去表达这种“组内差异”就很吃力这时候就该上 ACLAccess Control List。setfacl和getfacl是核心工具。常见用法setfacl -m u:alice:rw /data/project # 给用户 alice 单独授读写权限 setfacl -m g:devs:rx /data/project # 给组 devs 授读执行权限 setfacl -x u:alice /data/project # 移除用户 alice 的自定义规则 setfacl -b /data/project # 移除所有扩展 ACL 规则设置后执行getfacl /data/project输出里会多出一行user:alice:rw-之类的记录也就是说原来ls -l权限位之外还有一份更细粒度的授权清单存在。这也是之前提到ls -l显示号的原因。5.3 umask新文件与目录的“出厂默认权限”项目里经常遇到“为什么新建的文件是 644我却想要 660”的问题这背后是umask在起作用。umask不是修改权限位的命令而是决定“默认减去哪些权限”的掩码。默认权限的完整算法是文件的最大权限是 666目录的最大权限是 777实际默认权限 最大值减去 umask 值。如果 umask 是022那么新建文件为666 - 022 644新建目录为777 - 022 755。如果 umask 是077文件变600目录变700。查看当前值umask。临时修改umask 027。如果想永久修改写入/etc/profile或用户的~/.bashrc。团队协作时建议安全基线用077或027这样默认情况下其他组用户看不到你的文件避免“手滑把敏感数据暴露全组”。别小看这一步很多“权限事故”都是 022 或更宽松的 umask 把不该暴露的文件放出去了。6. sudo 权限管理给“管理员权限”装一道闸门6.1 为什么不用 su而是用 sudo很多新手习惯用su切到 root 干活。但服务器多人协同时共享 root 密码既无法追踪操作者身份又容易在交接时泄露。sudo的设计思路完全不同用户用自己的账号和密码提权执行记录留存在日志里并且可以精确限制“谁在哪些主机上以哪个用户身份执行哪些命令”。sudo的配置在/etc/sudoers文件里修改时必须用visudo命令因为它会先做语法检查防止你把 sudoers 改坏导致所有提权全线崩溃。我见过有人直接vim /etc/sudoers改坏后连sudo都执行不了只能找宿主机团队介入修复非常狼狈。6.2 sudoers 规则的三层结构一条 sudo 规则的基本格式是用户/组 主机 (身份) 命令实际拆解alice ALL(ALL) ALLalice 可以在所有主机上以任意身份执行任意命令这是“完全管理员”配置授予时要非常谨慎%devs ALL(ALL) ALLdevs 组所有成员拥有同等级权限bob ALL(ALL) NOPASSWD: /usr/bin/systemctlbob 执行 systemctl 时不用输密码carl ALL(ALL) /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginxcarl 只能执行指定的两个 systemctl 动作不能执行 start、stop、reload 等其他子命令。这里有一个细节sudo 的命令匹配是“前缀匹配”不是“命令名匹配”。如果规则写/bin/systemctl restart nginx用户实际执行/bin/systemctl restart nginx --extra-arg可能也会命中。更安全的做法是加上sudoers配合COMMAND后面的或者直接限制参数但这不是新手阶段必须掌握的记住一条规则写得越具体越安全。用sudo -l可以查看当前用户被授权执行的所有命令列表。每次给成员开 sudo 权限前先执行sudo -l复查一遍能有效避免“多给”的情况。6.3 用日志反查操作者配置好 sudo 之后日志默认记录在/var/log/auth.logDebian 系或/var/log/secureRHEL 系。当用户通过 sudo 执行命令时日志里会记下时间、用户、主机、原用户、执行命令等字段。排查“是谁改了系统文件”时这几乎是唯一的线索。所以我每次布置服务器任务时都会提醒成员优先使用 sudo 而不是 su即使你是唯一管理员日志也是未来排查的救命稻草。7. 常见问题与排查技巧实录7.1 遇到 Permission denied先检查哪几层很多新手一看到Permission denied就慌其实排查顺序是有迹可循的用ls -l看文件属主和属组是否对得上用id看当前用户实际所在的组检查目录路径上每一级目录的 x 权限中间某一个目录没有执行权限整个路径都会被拦断用getfacl看是否有扩展 ACL 覆盖了 chmod 设置检查是否设置了 setgid/粘滞位特别在共享目录时这影响删除和新建行为如果是挂载盘检查挂载选项里是否带noexec会禁止任何文件执行、nosuid忽略 setuid 位等。我之前排查过一个开发环境的问题用户明确有/home/data/work目录的权限但访问文件时一直提示权限不足。后来namei -l /home/data/work/report.txt一查发现/home/data这层目录权限是700属主是 root普通用户根本进不去。这个namei命令能按路径逐级检查每一层的权限比手动一层层ls -l高效得多值得记进你的工具箱。7.2 目录删不掉文件八成是粘滞位或目录权限问题“我是 root为什么删不了普通用户目录下的文件”答案往往不在文件本身而在目录。如果所在目录没有写权限或者设置了粘滞位只有文件属主或 root 才能删除。千万不要用chmod -R 777去突破正确做法是先确认为什么不允许删除再决定是否把目录权限设置改为770、2770之类或者用setfacl精确授权。公共目录里我习惯保留粘滞位以保证临时文件的清理权留在创建者手里避免误删他人数据。7.3 脚本明明有了 x 权限执行却说 Permission denied这种情况优先看脚本开头有没有有效且正确的解释器路径例如#!/bin/bash写在第一行其次是检查ls -l里是否呈现出-rw-------这种 600 情形下的可执行文件第三是看挂载选项比如/tmp可能默认noexec你在 /tmp 下写脚本给了 755 也跑不起来。遇到这种问题最简单的验证方法是把脚本挪到/home/user/bin下再执行一次能运行说明是挂载选项的问题不能运行则继续排查。7.4 sudo 时提示不在 sudoers 文件中这属于极其常见的一次性错误自行将普通用户加入了wheel组但新开的会话尚未生效或者该发行版的 sudo 仅认可sudo组而非wheel组。解锁方式也很简单切换到 root 账户如果你知道 root 密码执行visudo增加%wheel ALL(ALL) ALL或把用户加入正确组然后重新登录测试。这条经验特别适合刚接手陌生服务器的时候因为你永远不知道前任管理员用的是哪种组名。7.5 权限设置“看起来对”但行为不符合预期这类问题的隐蔽性很强往往是扩展 ACL 或特殊权限位在作怪。比如某文件明明 644但某用户就是能编辑用getfacl一看多出一行user:alice:rw-罪魁祸首在这里。再比如目录禁止其他用户写但里面某个子目录却设置了 setfacl里面的文件可以被人任意删除。建议在排查权限问题时把ls -l、getfacl、namei -l、mount | grep noexec四条命令的执行结果拼在一起看百分之九十的问题都能露出真面目。ls -l /path/to/file getfacl /path/to/file namei -l /path/to/file mount | grep /path8. 常用权限指令速查表与选择建议为了方便日常翻阅我把平时用到的权限指令简单归纳成一张表你可以直接保存下来指令作用常用示例chmod修改文件/目录普通权限位chmod 750 /datachown修改文件属主与属组chown -R alice:devs /datachgrp仅修改文件属组chgrp devs /data/fileumask设置新文件/目录默认权限掩码umask 027setfacl设置扩展 ACL 的细粒度权限setfacl -m u:alice:rw /datagetfacl查看扩展 ACL 规则getfacl /datauseradd创建用户useradd -m -s /bin/bash aliceusermod修改用户信息/附加组usermod -aG devs alicegpasswd管理用户组成员gpasswd -a alice devspasswd修改用户密码/锁定账户passwd alicesudo按授权规则临时提权sudo systemctl restart nginxvisudo安全编辑 sudoers 配置visudo -f /etc/sudoersnamei逐层解析路径权限namei -l /var/www/html/index.html使用建议就三条写权限比读权限重要得多。失去读权限最多是看不见失去写权限则意味着无法修改文件内容但更危险的是对目录的写权限因为它同时决定你能不能在目录里新建或删除文件。给进程或团队成员分配目录权限时能不给写就不给写。给目录授权时用“组”“ACL”组合而不是直接给单个用户逐条加规则。组规则维护成本低ACL 适合处理少数例外两者配合既灵活又不至于让权限表变成一锅粥。所有生产环境的权限变更先记录目标状态再执行指令最后用ls -l/getfacl验证。如果变更环节出错至少还能通过历史记录很快回退而不是靠记忆去猜。9. 我自己踩过之后才明白的三件事写到最后聊几个实际操作中的体会。第一千万不要迷信chmod 777。很多“临时能跑”的方案最后都会变成生产环境里的长期方案。特别是共享目录和上传目录777 等于把删除、篡改文件的权限交给了服务器上任意一个用户一旦系统里存在其他漏洞这条权限通道会让损失成倍扩大。换个思路权限不够就把访问者加入正确的组再通过 ACL 做例外多花的两分钟远比事后紧急修复来得省心。第二“属主”和“属组”永远先于权限位被确认。权限位再宽松如果属主/属组本身就对应着错误的人或组后面怎么调整都是白费力。每次拿到一台陌生服务器我习惯先ls -lidh看看几个关键目录的归属再cat /etc/group看有哪些重点组几秒钟就能摸清这套环境的权限设计思路。第三给重要脚本或者关键目录写权限变更时先复制一份再操作。听起来很基础但真遇到chown -R手滑把系统目录的属主改错了即便你能切换 root 重新找回恢复文件组归属也是极其头疼的过程。备份永远是权限操作里最便宜的保险。Linux 的权限指令并不多但每条指令背后都对应着一套安全设计逻辑。把基础打扎实再遇到“权限不足”的报错你就不会再病急乱投医而是顺着主体、权限位、目录层级、特殊位、ACL、日志这条线索一查一个准。