记一次 Linux “多人等权”共享目录的问题及解决

记一次 Linux “多人等权”共享目录的问题及解决

在实验室公用 Linux 服务器的多用户环境下,经常需要一个由多人平行读写执行的共享目录;兼顾可维护与最小化权限暴露。但遇到一些问题,探索后发现与 umask、sgid、目录可穿越 (x)、ACL继承都有关,暴露出自己在 Linux 运维功底方面的缺陷。特此记录,以供参考。


问题介绍

  • 服务器:Linux(Debian 系)

  • 需求:/proj/shared 下由多位成员协同读写代码与数据

  • 现状:已创建用户组 projgrp,将成员 A、B 都加入了该组

  • 问题现象:

    • 成员 A 能在 /proj/shared 写入,但成员 B 无法修改 A 创建的文件
    • A 在 /proj/shared 创建的新文件属组落在自己的主组,而不是 projgrp
    • 成员 B 登录后 cd /home/A/.../shared 报“权限不够”

经过研究,发现这些现象背后牵涉 目录执行位(x)umaskSGIDACL 以及 登录会话的组缓存 等机制。逐个解决后完成了需求,特此记录,以便有类似需求的读者参考。


知识回顾

  • umask:仅影响新建文件/目录的权限位(如 rw-rw-r--),并决定属组归属。

    • 常用:umask 0002 → 新文件 664,新目录 775
  • 目录执行位(x):对目录意味着“可穿越”。路径上的每一层目录都需要对访问者有 x,才能 cd 进去。

  • SGID(setgid):目录位设置 g+s 后,新建子目录一定继承父目录组;新建文件在多数本地文件系统上也会继承父目录组(更标准做法是配合 ACL 保证)。

  • ACL(访问控制列表)

    • setfacl -m ... 设置访问 ACL(立即作用于当前对象)
    • setfacl -d -m ... 设置默认 ACL(仅对将来新建的内容生效)
    • mask 条目会裁剪“命名用户/组”的有效权限(常见坑点)

根因剖析

  1. 路径上某层目录缺少执行位 x
    例:成员 B 需要穿越 /home/A 才能进入共享子目录,若 /home/A 对组没有 x,即使目标目录权限正确也进不去。

  2. 仅设置了组与权限,未设置 SGID
    结果:在共享目录中新建的文件仍归属用户的主组,而非协作组。

  3. 只在顶层目录设置了默认 ACL,子目录未继承
    结果:深层子目录中新建的文件不带默认 ACL,仍不可写。

  4. ACL 的 mask 把有效权限裁剪掉
    看到 #effective: r--/rw- 等提示,说明默认/访问 ACL 被 mask 限制。

  5. 用户会话未刷新组列表
    刚把用户加入协作组,当前 TTY/SSH 会话仍在用旧组缓存;需要重新登录或用 newgrp

  6. 文件系统或挂载选项未启用 ACL
    某些发行版或挂载方式需要显式 acl 选项。


解决方案

1) 组与顶层权限初始化

1
2
3
4
5
6
7
8
9
10
# 创建协作组
sudo groupadd projgrp

# 将成员加入组(示例:userA 与 userB)
sudo usermod -aG projgrp userA
sudo usermod -aG projgrp userB

# 共享目录属组与基本权限
sudo chgrp -R projgrp /proj/shared
sudo chmod 2775 /proj/shared # rwxrwsr-x(含 SGID)

27752 即 SGID;s 确保目录树中的新建内容倾向继承协作组。

2) 仅允许“穿越”上层私有目录

若共享目录位于某个私有家目录下(如 /home/userA/shared),给协作组一个最小的穿越权限:

1
2
# 仅允许组穿越(不可列目录),保护家目录隐私
sudo setfacl -m g:projgrp:--x /home/userA

不用把 /home/userA 改成 755;--x 足以穿过而看不到其他文件。

3) 递归设置 SGID + 访问 ACL + 默认 ACL

关键:对子目录也必须生效,因此做递归设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
DIR=/proj/shared
GRP=projgrp

# 确保整个目录树属组正确
sudo chgrp -R "$GRP" "$DIR"

# 给所有目录设置 rwxrwsr-x(含 SGID)
sudo find "$DIR" -type d -exec chmod 2775 {} +

# 访问 ACL:让协作组在现有内容上有 rwx
sudo setfacl -R -m g:$GRP:rwx,m::rwx "$DIR"

# 默认 ACL:让将来新建的内容自动带组 rwx(以及放开 mask)
sudo setfacl -dR -m g:$GRP:rwx,m::rwx "$DIR"

m::rwx 是 ACL 的 mask,不放开会“剪掉”有效权限,导致组写权限实测无效。

4) 成员 umask 设置

协作成员的 umask 设为 0002(常见 shell 的 ~/.zshrc~/.bashrc):

1
umask 0002

这确保新建文件是 664,目录是 775,符合“组可写”的协作预期。
注意:umask 不控制属组;属组继承依赖 SGID/ACL。

5) 刷新用户会话的组上下文

将成员加入协作组后,需要重新登录或临时执行:

1
newgrp projgrp

newgrp 会以该组为有效组启动一个子 shell,退出即可回到原会话。


验证

顶层目录必须具备 s 权限位

1
2
ls -ld /proj/shared
# 期待:drwxrwsr-x ... root projgrp ...

ACL 应包含默认与 mask

1
2
3
4
5
getfacl /proj/shared
# 期待含:
# group:projgrp:rwx
# default:group:projgrp:rwx
# default:mask::rwx

新建文件/目录测试

1
2
3
4
# 模拟成员 B 的新会话测试
sudo -u userB bash -lc 'umask 0002; touch /proj/shared/t.new; mkdir -p /proj/shared/subdir'
ls -l /proj/shared/t.new /proj/shared/subdir
# 期待:属组为 projgrp;文件 664,目录 775

总结

现象 排查点 处理
cd 报权限不够 路径某层目录缺 x 给协作组添加最小穿越 ACL:setfacl -m g:projgrp:--x /path/that/blocks
新文件属组不是协作组 目录/子目录没 SGID 递归:find DIR -type d -exec chmod g+s {} +
组无写权限(但 ACL 好像给了) mask 裁剪了有效权限 同时设置 m::rwx:访问与默认 ACL 都要设
只在顶层有效,子目录无效 只在顶层设了默认 ACL -R 递归设置访问与默认 ACL
成员刚加组仍不生效 会话组缓存 重登录或 newgrp projgrp
ACL 设置后无效果 文件系统未启用 ACL mount 检查;/etc/fstab 增加 acl,重挂载

在多人协作的公用服务器上,实现“等权共享目录”并不复杂,但需要系统性处理

  • 路径可穿越(x)
  • SGID 保证组继承
  • ACL(含 mask)保证权限一致性
  • umask 做默认位的兜底
  • 会话刷新确保新组即时生效

记一次 Linux “多人等权”共享目录的问题及解决

https://www.catop.top/2025/09/28/shared-group-in-linux/

作者

Catop

发布于

2025-09-28

更新于

2025-09-28

许可协议

评论