资讯动态

Linux权限管理详解:从ls -l、chmod到SGID与ACL实战

发布时间:2026/10/24 5:45:57 来源:尧图企业网站定制
如果你在 Linux 上敲过一次ls -l就一定见过那一串像密码一样的-rw-r--r--如果你还写过脚本、部署过服务大概率也被Permission denied拦下来过。权限是 Linux 里最基础、也最容易被跳过的一课会用chmod 777不算会权限管理真正理解“谁能对什么做什么”才能避免误删、越权访问和线上故障。本文围绕 Linux 权限管理的第一层——权限本身从ls -l的输出逐列拆解讲起覆盖 rwx 对文件和目录的不同含义、数字与符号两种改权限写法、属主属组、umask 默认权限、SUID/SGID/Sticky 特殊位最后用一个多用户协作目录的完整实战把这些知识串起来。无论你是刚接触 Linux 的学生还是需要经常在服务器上排查问题的后端开发者都可以跟着本文的命令在虚拟机里逐条跑一遍。1. Linux 权限管理到底在管什么1.1 从一次 Permission denied 说起在 Linux 里几乎所有的“权限问题”最终都会以两种形式暴露出来一种是命令直接报错比如bash: /root/test.sh: Permission denied、cp: cannot open x.log for reading: Permission denied另一种更隐蔽命令不报错但结果不对比如服务启动日志里出现“无法写入日志文件”或者上传文件后属主变成了www-data导致后续处理失败。这两种现象看起来完全不同根因却往往是同一个当前进程的有效用户身份对目标文件缺少它需要的那一位权限。所以要理解权限先要建立一个核心认知Linux 的权限判定不是“你是管理员就全能”而是“每一个进程都带着一个身份内核拿这个身份去和目标文件的权限位做比对”。这个身份由三部分组成真实用户 IDreal UID、有效用户 IDeffective UID、所属组集合supplementary groups。内核在做权限检查时主要看的是有效 UID 和有效 GID。这就是为什么同一台机器上你用root登录能改/etc/shadow切换成普通用户就提示“权限不够”文件本身没动变的是请求者的身份。理解了这一点后面所有的chmod、chown、umask才有意义——它们本质上都是在调整“文件的权限位”或者“进程的身份”让比对结果符合预期。1.2 权限的三要素属主、属组、其他Linux 的权限模型是经典的 UGO 模型即 User属主、Group属组、Other其他人。每一个文件或目录都同时绑定了两个身份标签和一个权限三元组属主owner文件的创建者默认就是属主但可以通过chown修改。属组group文件归属的组默认是属主的“主组”也可以通过chgrp或chown :group修改。其他other不属于上面两类身份的任何人。内核判断权限时的顺序是固定的并且是“短路”的先看你是不是属主是就只按属主位判断不再看组位不是属主再看你是不是属组成员是就只按组位判断都不是才走 other 位。这个顺序非常重要因为它意味着权限位之间不是“或”的关系而是“就近优先”。举个容易踩坑的例子某文件权限是-rw-r-----属主alice属组devs你是devs组成员但不是 alice。这时你按组位判断有读权限能cat。但如果文件是-rw-------属主 alice、属组 devs你虽然是同组组位是---照样读不了。很多人误以为“我是这个组的组位给了就有”实际上组位是---就等于没给组身份只是让你“有资格”走组位判断而已。1.3 为什么普通开发者也需要掌握权限有一种常见的说法是“权限是运维的事”。但在实际项目中权限问题几乎必然会落到开发者头上容器镜像里用非 root 用户启动进程日志目录写不进去CI 流水线拉代码后执行脚本提示没有执行权限上传目录被设成了777安全扫描直接报高危定时任务用crontab跑脚本失败手动sh script.sh却能跑通因为脚本没有 x 权限你用sh显式解释执行绕过了检查。这些场景都不需要你成为运维专家但需要你能读懂ls -l的九位权限、知道chmod改的是谁、知道目录的 x 位和文件的 x 位含义完全不同。本文后面的内容就按这个目标来组织先把现象和表示法讲透再进入实操。2. 环境准备与查看权限的基本命令2.1 实验环境说明本文所有示例都在标准的 Linux 发行版上验证思路主流的Ubuntu 20.04/22.04、CentOS 7/Stream、Rocky Linux、Debian都可以复现。由于不同发行版、不同版本在用户创建命令、默认 umask、SELinux 策略上存在差异具体输出可能与本文示例略有出入请以你机器的实际输出为准本文重点讲的是权限模型的通用规则这些规则在所有 Linux 发行版上是一致的。准备工作很简单建议在虚拟机或测试机上操作不要在生产服务器上练手一个可以sudo的普通账号或者直接使用root仅限实验环境。至少创建两个普通用户用于验证多用户场景下的权限差异。一个独立目录例如/data/lab作为实验区方便用完直接删除。如果你使用的是云主机或容器环境请务必确认这是你有权操作的测试环境。权限相关的命令中chown -R、chmod -R这类递归操作一旦作用到错误路径恢复成本非常高后面第 5 节会专门讲风险。2.2 ls -l 输出逐列拆解先来看最基础的一条命令ls -l /etc/passwd典型输出如下-rw-r--r-- 1 root root 2841 Mar 12 10:20 /etc/passwd这一行包含 8 个字段逐个看字段示例值含义第 1 列-rw-r--r--文件类型位 九位权限位第 2 列1硬链接数目录则是子目录数不含.和..第 3 列root属主用户名第 4 列root属组名第 5 列2841文件大小字节第 6~8 列Mar 12 10:20最后修改时间第 9 列/etc/passwd文件名第一列最关键。把它拆成四段-rw-r--r--。第一位是文件类型位后面九位分三组每组三位依次对应属主、属组、其他人。所以-rw-r--r--读作这是一个普通文件属主可读写属组可读其他人可读。再看一个目录的例子ls -ld /tmp输出drwxrwxrwt 15 root root 4096 Mar 12 10:22 /tmp注意两点第一查看目录本身的权限要用ls -ld直接ls -l /tmp列的是目录里面的内容第二这里的权限位是rwxrwxrwt最后一位是t而不是x这就是后面要讲的粘滞位Sticky Bit。2.3 文件类型位对照表第一位的取值有几种常见情况认得它们能帮你快速判断“这是不是我以为的那个东西”字符类型说明-普通文件文本、二进制、压缩包等d目录directoryl符号链接类似 Windows 快捷方式c字符设备如/dev/null、终端设备b块设备如/dev/sda磁盘s套接字文件socket进程间通信p命名管道FIFO初学者常犯的一个错误是看到一个文件是l开头却拿chmod去改它的权限改完发现不生效。原因是符号链接在 Linux 里权限位基本没有意义内核在绝大多数操作中会直接“跟随”链接到目标文件chmod link实际改的是目标文件在部分系统上则什么都不做。遇到这种情况请先ls -l看链接指向哪里再改真实路径。2.4 用 id 和 groups 确认自己的身份在排查权限问题之前第一件事应该是确认“我现在到底是谁”。这一步很多人会跳过结果在一台跳板机上折腾半天最后发现sudo没加、或者当前 shell 是别的用户的会话。whoami id groupsid的输出示例uid1000(alice) gid1000(alice) groups1000(alice),1001(devs)解释一下uid是用户 IDgid是主组 IDgroups是包含主组在内的所有组。权限判断中的“属组匹配”看的是这个 groups 列表而不只是主组。这一点非常关键用户 alice 的主组是 alice但她同时属于 devs 组那么一个属组为 devs 的文件她就能走组位判断。如果你刚用usermod -aG devs alice把用户加进组但groups里看不到 devs八成是因为当前会话的组信息在登录时就确定了必须重新登录或者新开一个终端会话才会生效。这是排查“明明加了组还是没权限”的头号原因后面第 9 节会再提一次。3. 九位权限位与 rwx 的真实含义3.1 rwx 对文件的意义对普通文件来说r、w、x的含义相对直观rread4可以读取文件内容。对应命令cat、less、cp作为源、grep等。wwrite8可以修改文件内容包括追加和截断。注意它不包含删除文件的权力。xexecute1可以把文件当作程序执行。对应./script.sh、直接运行二进制。这里有两个高频误区值得展开。第一个误区是“有 w 就能删文件”。实际上删除一个文件本质上是修改它所在的目录从目录的条目中移除这一项所以能否删除文件取决于父目录是否给了你w和x跟文件本身有没有w没关系。你可以做一个小实验在一个你自己有写权限的目录里创建一个权限为000的文件然后尝试rm它会发现能删掉。第二个误区是“有 r 就能执行脚本”。脚本的x位决定的是“能否作为程序直接运行”。如果脚本只有r没有x./script.sh会报Permission denied但bash script.sh或sh script.sh依然能跑通因为你只是把文件内容当作bash的输入读进去bash并不要求输入文件有执行位。这就是“手动能跑、cron 跑不了”的经典原因之一——cron 里写的是/path/script.sh直接执行而这个文件没有x。3.2 rwx 对目录的意义重点目录的权限含义和文件完全不同这是 Linux 权限里最容易被忽略、也最容易出错的部分。请把下面这张表记住权限对目录的含义对应操作r可以列出目录中的条目名ls、ls -l的文件名部分w可以在目录中创建、删除、重命名条目touch、rm、mv、mkdirx可以进入目录、访问其中的文件cd、按路径访问目录内文件关键在于目录的x位是“通行证”r位只是“看得见”。这带来几种组合理解它们就理解了目录权限r--只有读可以ls看到文件名但ls -l拿不到文件属性因为需要stat目录内的每个条目涉及进入目录也会提示Permission deniedcd进不去也读不了里面的任何文件。--x只有执行ls会报Permission denied但如果你知道确切文件名可以直接cat /dir/known.txt读到内容。这在实际中常被用来做“可猜测路径的弱保护”但绝不能当作安全手段。rwx完整权限能进、能看、能改。还有一个非常重要的推论访问一个深层文件路径上每一级目录都需要x权限。比如/data/project/src/main.c你要读main.c需要对/、/data、/data/project、/data/project/src每一级目录都有x同时main.c本身有r。少任何一环都会报Permission denied而且报错信息往往只指向最终文件容易误导你去改错地方。3.3 权限与常见操作的对应关系为了便于排错把“操作 → 需要什么权限”整理成一张速查表操作目标对象需要的权限cat file文件文件r 路径上所有目录xecho file文件文件w 路径上所有目录x./script.sh文件文件r 文件x 目录xrm file文件所在目录目录w 目录xmv file dir/两边目录源目录wx目标目录wxcd dir目录目录xls dir目录目录rls -l dir目录目录r 目录x这张表建议直接存下来。下次遇到Permission denied先定位“是哪一步操作、作用于哪个对象、需要哪一位”比盲目chmod 777有效得多也安全得多。4. 权限的两种表示法与 chmod 实战4.1 八进制数字表示法每一位权限都可以用一个数字表示r 4w 2x 1把需要的加起来就是这一位的值。三组权限连起来就是一个三位八进制数比如755属主421 7rwx属组401 5r-x其他401 5r-x常用组合的含义如下数字符号形式典型用途644rw-r--r--普通文本文件、配置文件600rw-------私钥、密码文件755rwxr-xr-x可执行程序、目录700rwx------私有目录664rw-rw-r--组内协作的普通文件775rwxrwxr-x组内协作的目录777rwxrwxrwx所有人可读写执行生产环境慎用数字法写起来快适合一次性设定完整权限。命令格式chmod 644 /data/lab/config.ini chmod 755 /data/lab/run.sh chmod 700 /data/lab/private4.2 符号表示法符号法的格式是[ugoa][-][rwx]可以针对某一类身份做增量修改这在“只想给组加一个写权限不想动其他位”时特别方便u属主g属组o其他a全部等价于ugo。增加-移除直接赋值会覆盖原有权限。chmod ux run.sh # 给属主加执行权限 chmod gw shared.txt # 给属组加写权限 chmod o-rwx secret.txt # 移除其他人的所有权限 chmod ar public.html # 所有人可读 chmod urw,gr,o log.txt # 直接赋值逗号分隔多组符号法还有一个组合写法很实用chmod x file省略身份等价于ax但要受 umask 影响准确写法还是显式写chmod ux或chmod ax。在脚本里建议显式写出身份可读性更好行为也更确定。4.3 递归修改与 X 权限位当目标是目录时-R会递归处理目录下的所有内容chmod -R 755 /data/lab/static但这里有个坑755会把目录下所有文件也变成带x的权限而普通文本文件通常不需要执行位。这时可以用大写的X注意是大写chmod -R urwX,gorX /data/lab/static大写X的规则是只有当目标本身是目录或者文件原本就有任意一位执行权限时才设置执行位。这正好符合“目录给 x、普通文件不给 x”的需求是部署静态资源、批量设置项目目录权限时的标准做法。4.4 关于 777 的误区chmod 777是新手最容易形成的条件反射改不好就 777。但 777 意味着任何人都能读、写、执行在 Web 目录上等于给了上传者一个可写入并执行脚本的入口在共享机器上等于放弃了对数据的控制。更现实的问题是777 会掩盖真正的问题——你原本只需要给属组加w结果把整个权限模型都拆了后续排查问题时反而看不清权限设计意图。正确的做法是先确定最小必要的权限再落地成具体数字。一个典型 Web 目录的合理权限是目录755属主www-data、上传目录775且属组正确、配置文件640。如果确实需要多用户协作请用“建组 组权限 SGID / ACL”来解决而不是 777。第 8 节的实战会完整演示这个流程。5. 属主与属组管理chown、chgrp5.1 chown 的基本用法chownchange owner用于修改文件或目录的属主和属组需要root或具有CAP_CHOWN能力的用户执行。普通用户即使用sudo也只在被授权时才能改。chown alice app.log # 只改属主 chown alice:devs app.log # 同时改属主和属组 chown :devs app.log # 只改属组等价 chgrp devs app.log chown alice: app.log # 属主改 alice属组改为 alice 的主组 chown -R alice:devs /data/lab # 递归修改整个目录注意chown alice:devs和chown alice.dev两种写法在大多数 GNU coreutils 环境下都支持但为了可读性和兼容性推荐统一使用冒号。chgrp是专门改属组的命令适合只需要改组不改属主的场景chgrp devs report.txt chgrp -R devs /data/project5.2 递归修改的风险与正确姿势chown -R是权限操作里最危险的一类命令因为它的作用范围由路径决定而路径写错一个字符影响范围可能完全不同。常见的错误有三种第一种是路径末尾多写或漏写斜杠导致作用到错误的层级第二种是在/或/usr、/var这类系统目录上误操作导致系统命令或服务异常第三种是没有确认当前目录误把.或*展开成意料之外的文件集合。降低风险的做法是固定的三步先确认路径、再预览、最后执行。# 第一步确认目标目录存在且正确 ls -ld /data/project # 第二步利用 find 预览将被影响的文件不实际修改 find /data/project ! -user alice -ls | head -20 # 第三步确认无误后再执行 sudo chown -R alice:devs /data/project对于生产环境还应该在变更前做备份或快照并把命令写成可回滚的形式。涉及大批量属主变更时建议分批执行并观察服务日志因为在变更过程中服务可能因为无法读取文件而短暂报错。5.3 属主与属组的实际场景属主属组的调整在几种场景下几乎不可避免。Web 服务目录Nginx / Apache 以www-dataDebian 系或nginx、apacheRHEL 系身份运行如果站点目录的属主是root且权限是755服务读得了但写不了上传和缓存目录。常见做法是站点代码属主为root:www-data、权限644/755仅上传目录设为www-data:www-data且权限755。容器与挂载卷容器内的进程通常以非 root 用户比如 UID 1000运行而宿主机挂载进去的目录属主可能是 root。这时容器内写文件就会Permission denied。解决办法是让宿主机目录属主与容器内 UID 对应或者启动容器时用--user指定 UID 并确保目录对该 UID 可写。代码交付从压缩包解压出来的文件属主可能是打包人的 UID落到服务器上变成一个陌生的数字 UID。ls -l里看到1001 1001这种数字而不是用户名就是这个原因——系统里没有对应的用户条目。这种情况下chown -R deploy:deploy是常规操作。6. 默认权限与 umask6.1 umask 的作用机制新建文件的权限不是靠“创建时就指定”而是有一套默认规则文件的基准权限是666不给执行位目录的基准权限是777然后减去 umask 中对应的位。注意这里是“按位清除”不是数学减法。umask的查看很简单umask # 输出如 0022 umask -S # 符号形式输出如 urwx,grx,orx常见的默认值root用户通常是0022普通用户在部分发行版上是0002组内可写。这个差异解释了一个常见困惑为什么在有的机器上新建文件是644在另一些机器上是664。6.2 计算示例以umask 022为例新建普通文件666按位减去022→644即rw-r--r--。新建目录777按位减去022→755即rwxr-xr-x。以umask 002为例新建普通文件666减去002→664即rw-rw-r--。新建目录777减去002→775即rwxrwxr-x。可以用一条命令验证umask 022 touch /data/lab/umask_test.txt mkdir -p /data/lab/umask_dir ls -ld /data/lab/umask_test.txt /data/lab/umask_dir预期输出类似-rw-r--r-- 1 alice devs 0 Mar 12 11:00 /data/lab/umask_test.txt drwxr-xr-x 2 alice devs 6 Mar 12 11:00 /data/lab/umask_dir6.3 临时设置与永久生效umask是进程级属性不是系统全局的。直接执行umask 002只影响当前 shell 及其子进程关掉终端就失效。如果想让某个用户长期使用特定 umask写入 shell 配置文件# 追加到 ~/.bashrc echo umask 002 ~/.bashrc如果要系统级统一可以修改/etc/profile或/etc/login.defs不同发行版位置和优先级不同修改前请先备份并确认发行版差异。对于组内协作目录除了 umask更可靠的方式是用 SGID 默认 ACL见第 8 节因为 umask 只影响“新建”对已经存在的文件无效而且用户自己随时可以改。7. 特殊权限位SUID、SGID、Sticky7.1 SUID以文件属主身份执行SUIDSet User ID位设置在可执行文件上时进程运行期间的有效 UID 会临时变成文件属主的 UID。最典型的例子是/usr/bin/passwd——它需要改写/etc/shadow而普通用户没有这个权限所以它带着 SUID 位运行临时获得 root 身份。查看方式ls -l /usr/bin/passwd输出中属主位的x会变成s-rwsr-xr-x 1 root root 59976 Feb 1 09:15 /usr/bin/passwd设置与取消chmod us /path/to/program chmod 4755 /path/to/program chmod u-s /path/to/program需要强调两点。第一SUID 只对二进制可执行文件有意义对 shell 脚本通常无效因为 Linux 内核出于安全考虑会忽略脚本上的 SUID 位。第二SUID 是提权相关的高危配置在生产环境中应该严格审查。系统里存在哪些 SUID 文件可以定期核查find / -perm -4000 -type f 2/dev/null如果你在排查安全问题时看到来源不明的 SUID 文件应当视为需要立即确认的可疑项。7.2 SGID对文件和目录的两种语义SGIDSet Group ID在不同对象上含义不同这一点经常被混淆。应用在可执行文件上时进程的有效 GID 会变成文件属组用途同样是临时借用组身份。应用在目录上时效果是在该目录下新建的文件和子目录会自动继承该目录的属组而不是创建者的主组。这是组内协作场景的核心工具。设置方式chmod gs /data/project # 符号法 chmod 2770 /data/project # 数字法2 是 SGID 位设置后ls -ld的输出中属组位的x变成sdrwxrws--- 2 root devs 4096 Mar 12 11:20 /data/project这里有一个必须知道的坑SGID 只保证“属组继承”不保证“组有写权限”。也就是说新建文件的属组会是 devs但它的权限位仍然由创建者的 umask 决定。如果 umask 是022新文件是644组内其他人只有读没有写协作写入依然做不到。解决办法是配合 umask002或者在目录上设置默认 ACL。这个坑在第 8 节会实际演示。7.3 Sticky Bit限制他人删除粘滞位Sticky Bit只对目录生效作用是即使所有人都对目录有写权限也只允许文件属主、目录属主和 root 删除或重命名目录内的文件。最经典的例子是/tmpls -ld /tmpdrwxrwxrwt 15 root root 4096 Mar 12 10:22 /tmp其他位是rwtx变成了t。这样/tmp虽然人人可写但你删不掉别人的文件。设置方式chmod t /data/shared chmod 1777 /data/shared # 1 是粘滞位7.4 大写 S 和 T 的含义有时候你会看到大写字母-rwSr--r-- drwxr-Sr-x drwxrwxrwT大写表示“特殊位已设置但对应的执行位没有设置”。因为s和t是占用x位置的显示如果原本没有x就只能显示大写。举个例子一个文件被chmod us但本身没有x就会显示s变S——这种情况在实际中通常意味着配置有问题因为一个不可执行的文件带 SUID 并没有实际意义。遇到大写字母时的排查思路是ls -l看到S或T先确认这个对象是否真的需要对应的特殊位再检查执行位是否被误移除。8. 完整实战搭建一个多用户协作目录8.1 需求描述假设有一个三人开发小组alice、bob属于devs组carol不属于该组。需求是创建共享目录/data/projectdevs 组成员在其中可以互相读写包括读取和修改对方新建的文件。目录及其中新建文件的属组统一为devs。非 devs 组用户carol无法进入该目录。这个需求用到的知识点正好覆盖本篇文章组、SGID、目录权限、默认 ACL。8.2 创建用户与组以下命令需要 root 或 sudo 权限请在测试环境执行sudo groupadd devs sudo useradd -m -G devs alice sudo useradd -m -G devs bob sudo useradd -m carol给用户设置密码便于切换验证sudo passwd alice sudo passwd bob sudo passwd carol注意useradd -G是把用户加入附加组主组仍然是同名组。不同发行版中useradd和adduser的行为不同adduser在 Debian 系上是交互式脚本创建时会顺带建家目录而useradd默认不建家目录需要加-m。这是跨发行版脚本容易出错的地方。创建完成后验证id alice预期输出中包含devsuid1001(alice) gid1002(alice) groups1002(alice),1001(devs)8.3 创建目录并设置基础权限sudo mkdir -p /data/project sudo chown root:devs /data/project sudo chmod 2770 /data/project逐条解释mkdir -p保证父目录不存在时自动创建。chown root:devs把属组设为 devs属主保持 root也可以换成某个管理员账号。chmod 2770中2是 SGID770表示属主和属组是rwx其他人没有任何权限。验证ls -ld /data/project预期drwxrws--- 2 root devs 4096 Mar 12 12:00 /data/project看到属组位的s说明 SGID 已生效。8.4 验证 SGID 与组协作写入先以 alice 身份操作su - alice cd /data/project echo hello from alice alice.txt ls -l alice.txt预期输出-rw-r--r-- 1 alice devs 17 Mar 12 12:05 alice.txt可以看到属组已经是devs继承自目录但权限是644。现在切换到 bob 尝试写入su - bob cd /data/project echo append by bob alice.txt此时大概率会报-bash: alice.txt: Permission denied这正是 7.2 节提到的坑SGID 解决了属组继承但文件权限只有属主可写bob 走组位判断组位是r--写不了。8.5 用默认 ACL 补上组写权限有两种解决方式。第一种是让所有 devs 组成员把 umask 设为002这样新建文件默认就是664。但 umask 是用户自己可控的别人改了 umask 就会破坏协作规则不够稳。更可靠的第二种方式是给目录设置默认 ACL让在该目录下新建的文件自动带上组写权限sudo setfacl -m g:devs:rwx /data/project sudo setfacl -d -m g:devs:rwx /data/project sudo setfacl -d -m o::--- /data/project参数说明-m表示修改 ACL 条目。g:devs:rwx表示给 devs 组授予读写执行。-d表示 default ACL只对目录中新创建的对象生效不影响已有文件。o::---表示其他人类别无权限保证非 devs 用户无法访问。验证 ACLgetfacl /data/project输出类似# file: data/project # owner: root # group: devs user::rwx group::rwx group:devs:rwx other::--- default:user::rwx default:group::rwx default:group:devs:rwx default:other::---现在再以 alice 新建一个文件然后看 bob 能否写入su - alice cd /data/project echo new file report.txt ls -l report.txt getfacl report.txt你会看到ls -l的权限位后面多了一个表示该文件带有 ACL-rw-rw-r-- 1 alice devs 9 Mar 12 12:15 report.txtgetfacl report.txt会显示group:devs:rwx的条目说明组写权限已经通过默认 ACL 继承下来。此时 bob 执行echo bob was here report.txt就能成功。最后验证 carol 无法访问su - carol cd /data/project预期报错-bash: cd: /data/project: Permission denied因为 other 位是---没有x就无法进入目录整个协作用户范围就被限制在 devs 组内了。8.6 完整流程回顾把上面的步骤串成一条可直接复制的脚本仅用于测试环境执行前请确认/data/project不存在或可覆盖#!/bin/bash set -e # 1. 建组建用户 groupadd devs || true useradd -m -G devs alice || true useradd -m -G devs bob || true useradd -m carol || true # 2. 建目录并设置属组与 SGID mkdir -p /data/project chown root:devs /data/project chmod 2770 /data/project # 3. 设置 ACL保证新建文件继承组写权限 setfacl -m g:devs:rwx /data/project setfacl -d -m g:devs:rwx /data/project setfacl -d -m o::--- /data/project # 4. 输出结果 ls -ld /data/project getfacl /data/project执行完成后用 alice 和 bob 互相写文件验证用 carol 验证拒绝访问这个流程就算完整跑通了。这套“建组 SGID 默认 ACL”的组合是 Linux 上实现多用户协作目录的标准做法比 777 安全得多也比单纯依赖 umask 可靠得多。9. 常见问题与排查清单权限问题的排查有一个固定套路确认身份 → 确认路径 → 确认每一级目录权限 → 确认目标对象权限 → 确认特殊机制ACL、SELinux、挂载选项。下面把高频问题整理成表格方便对照。问题现象常见原因解决思路-bash: ./x.sh: Permission denied脚本缺少x位chmod ux x.sh或改用bash x.sh手动能跑cron 跑不了cron 直接执行脚本缺x或环境变量不同给脚本加x位脚本内使用绝对路径明明在组里还是没权限组信息未生效需重新登录新开会话或newgrp devs验证ls能看到文件名但读不了内容目录有r无xchmod ux dir或按需调整知道完整路径就能读文件目录给了x没给r这是设计行为评估是否需要收紧改完权限不生效被 ACL 覆盖或是符号链接getfacl查看ls -l看标记服务写不了目录目录属主/属组与进程运行用户不一致对齐属主属组仅对必要目录放开写删除别人的文件失败目录设置了粘滞位确认是否应保留必要时由属主或 root 操作容器内写挂载目录失败容器内 UID 与宿主机目录属主不匹配调整宿主机目录属主或容器启动用户解压后属主显示为数字系统内无对应 UIDchown -R 目标用户:目标组除了表格里的原因还有两个容易被忽略的机制。第一个是SELinux。在启用了 SELinux 的 RHEL 系系统上文件权限全对服务依然可能报Permission denied。这时查看/var/log/audit/audit.log或执行getenforce确认状态。SELinux 属于强制访问控制和本文讲的普通权限是两层独立机制解决问题需要改上下文或策略而不是继续chmod。第二个是挂载选项。某些目录可能以noexec、ro等选项挂载导致即使文件有x位也无法执行或者根本无法写入。用mount | grep 目标路径确认挂载参数能省下大量无效排查。一个实用的排查清单遇到权限问题按顺序过一遍whoami、id当前身份和组是否如预期。ls -ld逐级检查路径上每一级目录的权限。ls -l检查目标文件本身的权限和属主属组。getfacl检查是否存在 ACL 覆盖。getenforce检查 SELinux 状态。mount检查目标路径的挂载选项。检查进程实际运行用户ps -o user,pid,cmd -p pid而不是“我以为的运行用户”。10. 最佳实践与学习路线10.1 权限设计的几条硬规则最小权限原则。给到刚好够用的权限不多给一位。Web 目录不需要777日志文件不需要666脚本不需要4777。每次要加权限时先问一句“能不能只给某一个组、某一个用户”。按组授权而不是按人授权。人多了以后逐个用户授权必然失控。正确做法是建业务组如devs、ops、www-data把用户加入组用组权限和 SGID 管理目录。这样人员的进出只需要维护组成员关系。敏感文件收紧到 600 或 640。私钥、数据库密码、.env文件、备份文件都属于这一类。特别注意不要把这些文件放在 Web 根目录下也不要在打包镜像时把它们带进镜像层。慎用递归操作。chmod -R和chown -R执行前必须预览路径必要时用find先列出受影响对象。生产变更前做快照或备份并准备好回滚命令。权限变更留痕。在团队环境里重要的权限调整应该有记录谁改的、为什么改、改之前是什么。哪怕是写在变更单里的一行备注出问题时也能节省大量时间。10.2 常规维护动作定期检查异常的高权限文件是一个成本很低但收益很高的习惯# 查找系统中所有 SUID 文件 find / -perm -4000 -type f 2/dev/null # 查找所有人可写的文件排除临时目录 find /data -type f -perm -ow 2/dev/null # 查找属主为陌生 UID 的文件 find /data -nouser -o -nogroup 2/dev/null | head -20这几条命令不需要天天跑但在接手一台旧服务器、做安全自查、或者排查异常行为时非常有用。特别是第三条能帮你发现从其他机器迁移过来、没有正确重设属主的文件。10.3 接下来可以学什么本文覆盖的是 Linux 权限模型的基础层UGO 三位九位、属主属组、umask、特殊权限位和 ACL。往下还有几个方向值得继续深入。第一个方向是ACL 的完整用法包括setfacl -x删除条目、-b清空所有 ACL、mask 的作用以及如何用getfacl输出做权限审计。协作目录场景下ACL 比传统 UGO 灵活得多值得系统学一遍。第二个方向是sudo 与提权管理。/etc/sudoers的规则写法、NOPASSWD的风险、visudo的校验机制、按命令粒度授权是团队环境中控制 root 使用的核心。第三个方向是SELinux / AppArmor。当你发现权限位都正确但服务依然被拒绝时强制访问控制就是下一层要排查的地方。第四个方向是容器与权限。Docker 的--user、USER指令、rootless 模式、挂载卷的 UID 映射都是把本文的权限知识应用到容器场景后的延伸。建议的学习方式是在一台测试机上把本文第 8 节的协作目录完整做一遍然后故意制造几种错误去掉x位、改错属组、加上粘滞位观察每种错误的报错表现。权限这块知识的特点是“看懂了”和“会用”之间隔着一层手感只有真正敲过命令、见过报错下次在服务器上遇到Permission denied时才能几分钟定位而不是先去搜索“Linux 权限不够怎么办”。

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

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

免费获取报价 →
↑