第 5 章 · 04 属主与属主组:`chown`、`chgrp`


文档摘要

第 5 章 · 04 属主与属主组: 、 本节摘要:前三节你学了「权限位」和「改权限」,但权限位只是「已确认身份后,允不允许你做」。身份本身是怎么确定的? 这就是 (改属主)和 (改属组)的主题。每个文件都有「属主」「属组」两个标签,决定了你在 / / 三类人里属于哪一类。本节要讲清三件事: 同时改主组的设计、权限检查「先属主→属组→其他,命中即止」的顺序(这正是为什么属主权限有时反而比其他小的反直觉现象),以及为什么只有 root 能 (普通用户不能「赠送」文件给别人,否则审计会乱)。理解了身份,你才算真正理解 Linux 权限系统。 内容来源:原项目「Linux 命令大全」 与 ,精选并套用体系化模板。

第 5 章 · 04 属主与属主组:chownchgrp

本节摘要:前三节你学了「权限位」和「改权限」,但权限位只是「已确认身份后,允不允许你做」。身份本身是怎么确定的? 这就是 chown(改属主)和 chgrp(改属组)的主题。每个文件都有「属主」「属组」两个标签,决定了你在 u/g/o 三类人里属于哪一类。本节要讲清三件事:chown user:group 同时改主组的设计、权限检查「先属主→属组→其他,命中即止」的顺序(这正是为什么属主权限有时反而比其他小的反直觉现象),以及为什么只有 root 能 chown(普通用户不能「赠送」文件给别人,否则审计会乱)。理解了身份,你才算真正理解 Linux 权限系统。

内容来源:原项目「Linux 命令大全」command/chown.mdcommand/chgrp.md,精选并套用体系化模板。

学习目标

阅读完本节,你应当能够:

  1. chown user:group file 同时修改属主与属组,以及 chown user file(只改属主)、chown :group file(只改属组)的简写。
  2. chgrp group file 单独改属组,理解它与 chown :group 的等价关系。
  3. 说清 Linux 权限检查的顺序:「先看是不是属主→再看是不是属组→最后归为其他,命中即止」。
  4. 解释「为什么属主权限有时反而比其他小」这种反直觉现象(命中即止导致的)。
  5. 理解「只有 root 能 chown」的设计动机(防止用户把文件「甩锅」给别人规避审计)。

一、设计动机:权限检查的前提是「你是谁」

第 01 节讲过,每个文件有「属主 u、属组 g、其他 o」三类权限。但 Linux 在你访问文件时,怎么决定你属于哪一类? 答案藏在两个标签里:每个文件都有「属主」(owner)和「属组」(group)两个元数据,记录在它的 inode 中。

$ ls -l notes.txt -rw-r--r-- 1 alice dev 651 Aug 4 notes.txt # ↑ ↑ # 属主 属组
  • 属主:alice,即「这个文件的主人」。
  • 属组:dev,即「这个文件所属的用户组」。

当你(bob)访问 notes.txt 时,Linux 按以下顺序判断你属于哪一类:

1. 你是不是 alice? 是 → 用 u 的权限(命中即止) 2. 你是不是 dev 组的成员? 是 → 用 g 的权限(命中即止) 3. 都不是 → 用 o 的权限

关键概念:「先属主→属组→其他,命中即止」。Linux 不会「叠加」权限——如果你是属主,就只用属主那组权限,即使属组或其他的权限更大,也不会「补」给你。这个规则解释了一个反直觉现象,见下文踩坑。

chown 改的就是这两个标签

chown(change owner)改属主,顺便也能改属组。它的几种形式:

chown alice notes.txt # 只改属主为 alice, 属组不变 chown :dev notes.txt # 只改属组为 dev, 属主不变 chown alice:dev notes.txt # 同时改属主 alice 和属组 dev chown alice: notes.txt # 属主改 alice, 属组改为 alice 的主组(冒号后留空)

chgrp(change group)只能改属组,等价于 chown :group:

chgrp dev notes.txt # 等价于 chown :dev notes.txt

💡 技巧:实务里几乎只用 chown,不用 chgrp。因为 chown user:group 一条命令就能同时搞定主组,而 chgrp 只能改组。记住 chown 一种就够,chgrp 知道它存在即可。

只有 root 能 chown

$ whoami bob $ chown alice notes.txt chown: changing ownership of 'notes.txt': Operation not permitted

普通用户不能把自己文件的属主改成别人。这是设计使然,不是 bug——如果允许,你就能「把自己的文件甩锅给 alice」,让 alice 为你的行为背锅,系统审计就乱了。只有 root 能 chown 给别人。但 chgrp 例外:普通用户可以把自己的文件改到自己所属的某个组(只能给组,不能给主)。

二、高频组合与实战

1. 部署 web 项目:整目录改属主属组

web 服务器以 www-data 用户运行,你部署的项目要让 www-data 能读写:

sudo chown -R www-data:www-data /var/www/mysite # -R 递归, 把整个目录树的主组都改成 www-data

-Rchmod -R 类似,递归改整棵树。这是部署 web 应用的高频操作。

2. 与 chmod 配合:先定身份、再定权限

sudo chown -R deploy:deploy /opt/app sudo chmod -R 750 /opt/app # 属主 rwx, 属组 r-x, 其他无

权限管理的标准流程是「先 chown 定身份,再 chmod 定权限」。先确定「谁是属主、谁是属组」,再决定「属主能干啥、属组能干啥」。顺序反了会出错——比如先 chmodchown,中间窗口期权限对的是旧属主。

3. 把文件交给某个组共享

sudo chgrp dev shared_doc.txt # 改属组为 dev sudo chmod 660 shared_doc.txt # rw-rw----: 属主和属组都能改, 其他无

这样 dev 组的所有成员都能读写 shared_doc.txt,组外的人什么都看不到。这是「组内协作」的标准模式。

4. 修改属主的同时让它归到主组

sudo chown alice: report.txt # 属主 alice, 属组自动设为 alice 的主组

alice:(冒号后留空)是便捷写法:属主设为 alice,属组设为 alice 的「主组」(在 /etc/passwd 第四字段定义)。这在创建用户家目录文件时很常用。

5. 查看用户与组的对应关系

chown 之前你得先知道「有哪些用户、用户在哪些组」。常用工具:

$ id # 当前用户的身份信息 uid=1000(bob) gid=1000(bob) groups=1000(bob),27(sudo),1001(dev) $ groups alice # 看 alice 在哪些组 alice : alice dev docker $ getent group dev # 看 dev 组里有哪些人 dev:x:1001:alice,bob,carol

id 看自己、groups 用户名 看别人、getent group 组名 反查组成员——这三个命令是身份管理的「侦察三件套」。设计组协作权限前,先用它们摸清「谁是谁、谁在哪个组」,避免改完权限才发现「以为他在 dev 组,其实不在」。

💡 技巧:用户可以属于多个组(除了主组还有附加组),groups 输出的第一个是主组。权限检查时,只要你是某个组的成员(主或附加都算),就用那个组的 g 权限。

6. 把目录连同内部所有文件交给某个用户

服务迁移时常见:把整个 /opt/oldapp 交给新运维 ops:

sudo chown -R ops:ops /opt/oldapp # -R 递归, 整棵树改主组 sudo find /opt/oldapp -type d -exec chmod 755 {} \; # 顺手重置权限 sudo find /opt/oldapp -type f -exec chmod 644 {} \;

迁移的标准动作是「chown -R 改身份 + find ... chmod 重置权限」两连。先改身份再定权限,顺序与上文「先 chownchmod」一致。

三、踩坑与排错

坑 1:属主权限反而比其他小——「命中即止」的坑

最反直觉的现象:你明明是属主,却打不开自己的文件。

$ ls -l myown.txt -r------w- bob bob ... # 属主 r--, 属组 ---, 其他 -w- $ whoami bob $ cat myown.txt # 我是属主, 但只有 r, 能读 (成功读出) $ echo hi >> myown.txt # 我想写, 属主没有 w! bash: myown.txt: Permission denied

奇怪的是:myown.txt 的「其他」是 -w-(有写权限),bob 也是属主。为什么 bob 写不进去?因为权限检查「命中即止」——bob 是属主,匹配了 u 那一组(只有 r),就不再看 go 了。即使 o 那一组有 w,也轮不到 bob 用。

关键概念:权限不是「取并集」,而是「按顺序匹配,命中即止」。属主权限即使比其他小,属主也只能用属主那组权限。这就是为什么有时「其他人能改、属主反而不能改」这种怪事——通常是配置失误,但能解释清楚就是真懂了。

坑 2:普通用户试图 chown 失败

$ chown alice myfile # 普通用户改属主 chown: ... Operation not permitted

记住:只有 root 能改属主。普通用户只能 chgrp 到自己所属的组。如果你看到这条报错,不是文件坏了,是你权限不够——加 sudo

坑 3:chown -R 把符号链接的目标也改了

sudo chown -R deploy:deploy /opt/app # /opt/app/link 是个符号链接指向 /etc/config # chown -R 默认会跟随链接, 把 /etc/config 的属主也改成 deploy! (危险)

默认情况下 chown -R 会跟随符号链接改目标文件。要避免,加 -h(或 -P)选项,只改链接本身。实务上对包含符号链接的目录 chown -R 要格外小心,最好先 find -type l 看看有没有链接。

坑 4:把属主改成不存在的用户

sudo chown nonexistent notes.txt # 用户名打错了或用户已删 chown: invalid user: 'nonexistent'

chown 会先校验用户/组是否存在(查 /etc/passwd/etc/group),不存在就报错。这是好事——避免了把文件挂到一个幽灵用户名下。但如果你用数字 UID(如 chown 1000 file),chown 不会校验该 UID 是否真有对应用户,要小心。

坑 5:误以为改了属组就立刻能写

sudo chgrp dev report.txt sudo chmod 640 report.txt # rw-r-----: 属组只有 r, 没有 w # dev 组成员想写? 不行, 还得 chmod 660

改属组只是「定身份」,权限还得 chmod。新手常以为「我把你加到 dev 组了,你就能改了」——错,要看属组那组权限里有没有 w。身份和权限是两个维度,缺一不可。

坑 6:加组成员后,正在登录的会话不立即生效

sudo usermod -aG docker bob # 把 bob 加到 docker 组 # bob 当前打开的终端: id 显示 groups 里没有 docker! # 必须重新登录, 或 newgrp docker 切换组上下文

用户组变更对「已登录的会话」不生效——组的成员关系在登录时读入,之后缓存在会话里。要让变更生效,退出重新登录(或临时用 newgrp 组名 开一个子 shell)。这是新手折腾半天「明明加了组却用不了」的常见原因。

⚠️ 注意:usermod -aG 一定要带 -a(append 追加),不带的话会把用户从其他附加组全移除,只留你指定的那一个——这是灾难性操作。记不住就记一句话:-aG 永远成对出现

坑 7:chown 后 SELinux/AppArmor 上下文丢失

在启用了 SELinux(CentOS/RHEL 默认)或 AppArmor(Ubuntu 默认)的系统上,chowncp 后文件的安全上下文(security context)可能不对,导致服务仍访问不了。这时要看的不只是传统权限:

ls -Z /var/www/html/index.html # -Z 显示 SELinux 上下文 # unconfined_u:object_r:httpd_sys_content_t:s0 ← 正确的 web 内容上下文 sudo restorecon -R /var/www/html # 恢复默认上下文

传统权限(rwx)是第一道门,SELinux/AppArmor 是第二道门。两道门都得过,服务才能真正访问文件。遇到「权限都对,服务还是报 Permission denied」,想想第二道门。这是第 8 章(sudo/服务用户)会更深入的话题。

四、权限排查的完整心智模型

把身份(chown)+ 权限(chmod)+ 目录关卡(第 03 节)+ 高级安全(SELinux)整合成一个排查流程:

服务访问不了文件, 报 Permission denied? │ ├─ 第 1 步: ls -l 文件 → 看传统权限位 │ └─ 权限位对吗? 服务用户能匹配 u/g/o 哪一组? │ ├─ 第 2 步: ls -ld 每一级父目录 → 看是否有 x │ └─ 任一父目录缺 x, 服务就穿不过去 │ ├─ 第 3 步: ps aux | grep 服务名 → 确认服务实际运行用户 │ └─ 想当然地以为是 root? 可能是 www-data、nobody │ ├─ 第 4 步: id 服务用户 → 看它在哪些组 │ └─ 以为它在 dev 组? 用 groups 实际查一遍 │ ├─ 第 5 步: ls -Z 文件 → 看 SELinux 上下文 │ └─ 上下文不对? restorecon 修复 │ └─ 第 6 步: lsattr 文件 → 看扩展属性 └─ 有 i(immutable)? chattr -i 解除

这个流程从「最常见的原因」往「最罕见的原因」排查,90% 的权限问题在第 1-4 步解决,第 5-6 步是进阶。养成「按顺序排查」的习惯,不要一上来就 chmod 777——那是放弃思考。

关键概念:chmod 777 是权限排查的「白旗」——它意味着「我搞不清楚谁该有权限,干脆全放开」。这在生产环境是严重的安全事故。正确的做法是按流程定位到「服务用哪个身份、需要哪个权限位」,精确授予

💡 技巧:善用 sudo -u 服务用户 cat 文件 实测。与其在脑内推演权限,不如直接切到服务用户身份跑一遍——sudo -u www-data cat /var/www/html/index.html,能不能读立刻见分晓,比任何理论分析都快。

本节要点回顾

  1. 每个文件有「属主」和「属组」两个标签,记录在 inode 里,决定了你访问时属于 u/g/o 哪一类。
  2. chown user:group file 同时改主组;chown user file 只改主;chown :group file(或 chgrp group file)只改组。实务几乎只用 chown
  3. 权限检查顺序:先属主→属组→其他,命中即止——权限不是「取并集」,匹配到哪组就用哪组。
  4. **「属主权限反而比其他小」**是命中即止的结果,不是 bug——属主即使权限小,也只能用属主那组权限。
  5. 只有 root 能 chown(普通用户不能送文件给别人);普通用户只能 chgrp 到自己所属的组。
  6. 权限管理标准流程:「先 chown 定身份,再 chmod 定权限」,顺序别反。
  7. chown -R 会跟随符号链接,可能误改链接目标的属主,加 -h 避免。

下一节进入「默认权限」:umask。当你新建一个文件,它的权限是怎么来的?为什么 touch 一个新文件是 644 而不是 777?答案在 umask 这个「权限掩码」里。它从一个反向角度保证了系统的安全默认值——「默认不给其他用户写权限」。


发布者: 作者: 灏天文库 转发
评论区 (0)
U