【linux运维】ubuntu+samba 用户组独占目录权限配置踩坑记

文章目录

背景

最近团队里要新开一个数据集目录,只想让固定几个人能往里写东西,其他同事只能拷贝、只读,不能瞎改。本来以为 chmod 三下五除二就能搞定,结果一路踩了好几个坑------从"这个组有哪些人都搞不清",到"nologin 账户怎么切换",再到最后 Windows 那边 SMB 死活拒绝访问。整个过程记录下来,给同样场景的朋友省点排查时间。

环境说明:

配置项 详情
系统 Ubuntu(Dell PowerEdge R740xd 服务器)
共享服务 Samba
涉及目录 /hqdata/shares/algo-test
目标账户 AAAA(新建,只用来"拥有"文件,不需要真正登录)

一、先摸清楚现有的用户和组关系

在动手改权限之前,一定要先弄清楚"谁在哪个组里",不然容易改错。

1. 看当前用户自己的组

bash 复制代码
groups          # 只列组名
id               # uid/gid/所有附加组,信息最全

id 的输出长这样:

复制代码
uid=1000(myaccount) gid=1000(myaccount) groups=1000(myaccount),27(sudo)

2. 看指定用户的组

bash 复制代码
id 用户名
groups 用户名

3. 看某个文件/文件夹当前的属主和属组

这一步特别关键,很多权限问题一上来就该先看这个:

bash 复制代码
ls -ld /path/to/folder

输出类似:

复制代码
drwxr-xr-x 2 BBBB developers 4096 Sep 18 10:00 /path/to/folder

第三列是属主,第四列是属组。

4. 看系统里所有的组、以及某个组的成员

bash 复制代码
cat /etc/group          # 系统所有组
getent group 组名        # 查某个组的成员

⚠️ 避坑提示 :/etc/group 每一行结尾的成员列表,只包含把这个组当附加组 的用户,某个用户如果是这个组的主组(primary group) ,不会出现在这个列表里,得用 id 用户名 看 gid= 那部分才准确。

二、创建一个专属用户组,只放一个用户

假设我要新建一个 test 组,只让 AAAA 这一个人在里面。第一步别急着建组,先确认一下这个组名有没有被占用:

bash 复制代码
getent group test

如果没有任何输出,说明组名可用,可以放心建:

bash 复制代码
sudo groupadd test

⚠️ 避坑提示 :如果 getent group test 已经有输出(比如显示了别的成员),说明这个组名已经被占用了,直接往里加人会导致原来那些人也拿到你接下来要设置的目录权限。这种情况建议换个不会撞车的组名,比如 algo-test-group。

三、创建一个"只拥有文件、不能真正登录"的账户

团队里已经有一个类似的账户 BBBB,专门用来当文件属主,平时不需要真人拿它登录服务器。我想让新账户 AAAA 也照这个模式建。

先看一下 BBBB 现有的配置长什么样:

bash 复制代码
getent passwd BBBB
复制代码
BBBB:x:1012:1012::/home/BBBB:/usr/sbin/nologin

拆开看,最后一段 /usr/sbin/nologin 就是关键------这个账户的登录 shell 被设成了 nologin,意味着它从设计上就不允许交互式登录,不管密码对不对,尝试登录都会被拒绝。

照着这个模式建 AAAA:

bash 复制代码
sudo useradd -m -s /usr/sbin/nologin AAAA
sudo passwd AAAA
  • -m:自动创建家目录,避免出现"配置里写着有家目录,实际却没建"的尴尬情况;
  • -s /usr/sbin/nologin:直接禁用交互式登录,和 BBBB 保持一致。

建完验证一下:

bash 复制代码
getent passwd AAAA
复制代码
AAAA:x:1013:1013::/home/AAAA:/usr/sbin/nologin

再把它加进 test 组:

bash 复制代码
sudo usermod -aG test AAAA

⚠️ 避坑提示 :这里的 -a(append)千万别漏!如果只写 -G test,会把这个用户原来所有的附加组全部清空 ,只留下 test 一个,是个很容易踩的坑。

验证一下组关系:

bash 复制代码
id AAAA
复制代码
uid=1013(AAAA) gid=1013(AAAA) groups=1013(AAAA),1014(test)

怎么"扮演"一个 nologin 账户去测试权限

因为 shell 被设成了 nologin,正常的 su AAAA 会直接报错:

复制代码
This account is currently not available.

正确的绕过方式是用 sudo -u 显式指定一个可用的 shell:

bash 复制代码
sudo -u AAAA /bin/bash

这样能拿到一个真正以 AAAA 身份运行的 bash 会话,可以正常测试她对文件的读写权限,操作完 exit 退出就行,不会对账户本身的登录配置做任何永久改动。

四、创建目标目录并设置基础权限

因为 AAAA 对共享目录的上层(比如 /hqdata/shares)本来就没有写权限,新目录得先由有权限的账户(比如管理员)建出来,再把属主转交给 AAAA:

bash 复制代码
sudo mkdir /hqdata/shares/algo-test
sudo chown AAAA:test /hqdata/shares/algo-test
sudo chmod 755 /hqdata/shares/algo-test

755 展开是 rwxr-xr-x:属主读写执行,属组和其他人都只能读、进目录、拷贝,不能改。

到这一步,如果只是想让 AAAA 一个人拥有完整权限、其他人(包括 test 组里未来加进来的其他人)都只读,配置已经够了。

五、让整个 test 组都能读写(不只是属主一个人)

后来发现需求变了------不只是 AAAA 一个人能写,而是希望以后往 test 组里加的所有人,都能自动对这个目录树拥有完整权限。这时候思路要从"锁定属主"切换成"锁定属组"。

关键是两个机制配合:

  • setgid 位 :保证以后在这棵目录树下新建的子目录 ,自动继承属组为 test,而不是继承创建者自己的主组;
  • 属组权限设为 rwx :让 test 组的所有成员都能读写执行,不只是属主。
bash 复制代码
sudo chgrp -R test /hqdata/shares/algo-test
sudo chmod -R 2775 /hqdata/shares/algo-test

2775 拆开:

  • 开头的 2 是 setgid 位;
  • 属主 rwx;
  • 属组(test)rwx ✅;
  • 其他人 r-x。

验证一下:

bash 复制代码
ls -ld /hqdata/shares/algo-test
复制代码
drwxrwsr-x 2 AAAA test 4096 Sep 29 17:48 algo-test

第4位是小写的 s,说明 setgid 生效了。这时候如果用 AAAA 身份在里面建一个子目录,子目录会自动带上 test 属组和 setgid 位,不需要每层手动重复设置。

六、用默认ACL堵住最后一个漏洞

setgid 只保证了"属组是谁"会被继承,但属组具体有没有写权限,还是取决于创建者当时的 umask 。如果哪天有个组成员的 umask 恰好是比较严格的 022,他新建出来的子目录属组权限就会变成只读,达不到"组内所有人都能写"的效果。

更稳妥的做法是给目录设置默认ACL ------目录专属的一种规则,效果是:目录下新建的任何文件/子目录,自动套用这个规则,而且这个规则会一路传给子目录的子目录,不受创建者 umask 影响。

bash 复制代码
sudo setfacl -R -d -m u::rwx /hqdata/shares/algo-test
sudo setfacl -R -d -m g::rwx /hqdata/shares/algo-test
sudo setfacl -R -d -m o::rx  /hqdata/shares/algo-test
  • -d:default ACL,只对目录有意义,表示"这个目录下新建的东西自动套用这条规则";
  • -R:递归应用到已存在的所有子目录。

验证:

bash 复制代码
getfacl /hqdata/shares/algo-test
复制代码
# file: hqdata/shares/algo-test
# owner: AAAA
# group: test
# flags: -s-
user::rwx
group::rwx
other::r-x
default:user::rwx
default:group::rwx
default:other::r-x

看到 default: 开头的几行就说明配置已经生效了。

实测:故意换一个"苛刻"的 umask,验证规则不受影响

bash 复制代码
sudo -u AAAA bash -c "umask 022; mkdir /hqdata/shares/algo-test/test-umask022"
getfacl /hqdata/shares/algo-test/test-umask022

就算故意把 umask 设成 022,新建目录的 group:: 那一行也应该依然是 rwx,而不是 r-x------这才说明真正摆脱了对 umask 的依赖,不再靠运气。

⚠️ 避坑提示 :默认ACL只保证"新建时"套用规则,如果以后有人手动 chmod 把某个子目录改坏了(比如误操作设成 777),ACL 不会主动纠正已存在的错误权限。如果目录用得比较频繁,建议定期跑一下巡检:

bash 复制代码
find /hqdata/shares/algo-test ! -group test           # 找属组异常的项
find /hqdata/shares/algo-test -type d ! -perm -g+w     # 找属组没有写权限的项

七、Windows 那边 SMB 映射死活"拒绝访问"

目录权限配好了,以为大功告成,结果 Windows 上用 AAAA 账户登录 SMB 共享,一直提示"拒绝访问"。

第一步排查:Samba 用户和 Linux 用户是两套账户体系

这是最容易被忽略的一点------Linux 系统账户和 Samba 账户是分开存储的,即便 Linux 那边账户、密码、组全配好了,Samba 服务照样不认识这个用户,除非专门给它建了 Samba 账户。

bash 复制代码
sudo pdbedit -L | grep AAAA

如果这条命令没有任何输出,说明这个用户压根没有 Samba 账户,这就是拒绝访问的直接原因。解决方法:

bash 复制代码
sudo smbpasswd -a AAAA

执行后会让你单独设一次 Samba 密码(可以和 Linux 密码一样,也可以不同,是两套独立体系)。

再确认一下账户状态是不是启用的:

bash 复制代码
sudo pdbedit -Lv AAAA

留意 Account Flags 那一行,正常是 [U ];如果看到 D 字样说明被禁用了,需要:

bash 复制代码
sudo smbpasswd -e AAAA    # -e 表示enable,启用账户

第二步排查:路径链上每一层的执行权限有没有断掉

即使目标目录本身权限没问题,如果上级目录没给执行权限,Samba 也没法"穿过"上级目录访问到深层目录,同样会报拒绝访问。用这条命令把路径上每一层的权限都列出来:

bash 复制代码
namei -l /hqdata/shares/algo-test
复制代码
f: /hqdata/shares/algo-test
drwxr-xr-x root     root       /
drwxr-xr-x root     root       hqdata
drwxr-xr-x root     root       shares
drwxrwsr-x AAAA     test       algo-test

留意每一层最后的执行位(x),只要中间某一层对目标用户来说缺 x,就会导致"看得到共享名字,但进不去"。

第三步排查:smb.conf 里的访问控制配置

bash 复制代码
cat /etc/samba/smb.conf

重点检查对应共享段里的这几项:

  • valid users:如果写了这一项,只有列在里面的用户/组才能访问,常见写法是 valid users = AAAA, @test(@ 前缀代表按 Linux 组授权,组内所有人自动被允许,不用每次单独加用户名);
  • invalid users:如果目标用户被明确写在这里,同样会被拒绝;
  • read only:如果设成 yes,即便文件系统权限允许写,Samba 层面也会先把写操作拦掉。

改完配置记得重启服务:

bash 复制代码
sudo systemctl restart smbd

还是不行?直接看 Samba 日志

日志里通常会给出确切原因:

bash 复制代码
sudo tail -50 /var/log/samba/log.smbd

重新在 Windows 上映射一次,让报错"新鲜出炉",再看日志最后几行,一般能看到类似 NT_STATUS_ACCESS_DENIED 的字样,并提示具体是哪条规则拒绝的。

总结

这次踩坑最大的感悟是:普通的 user/group/other 三段式权限,搞不定"给某个组的所有成员开放写权限,同时保证以后新建的子目录也自动生效"这种需求 ,必须靠 setgid 位 + 默认ACL 两个机制配合才能做到"以后不用手动干预,规则自动传递到任意深度"。另外 SMB 共享这块也提醒了我一句话:Linux 系统账户和 Samba 账户是两套完全独立的体系,配置权限时容易只顾着 Linux 这边,却忘了 Samba 那边也要单独建账户,这个坑排查起来最费时间。

相关推荐
wtblszn1 小时前
空压机在线监测物联网方案
大数据·运维·物联网·自动化·能源
AR-26710-1 小时前
Linux Day15——系统管理复习
linux·运维
高山有多高1 小时前
【Linux笔记】Linux自定义Shell
linux·c++
姜鱼问生2 小时前
HTTPS 部署实战:未备案域名 + 非标端口的完整方案
linux·https
jackletter2 小时前
linux:安装 ubuntu 26.04.1
linux·ubuntu·ubuntu26.04.1
打工仔折腾 AI2 小时前
飞牛OS上用Docker Compose部署ExerciseDiary运动记录并配置远程访问
运维·人工智能·后端·python·docker·容器·ai agent 实战
2401_869769592 小时前
make 进度条
linux
天远数科2 小时前
零信任架构实战:基于天远运营商三要素简版V即时版查询构建自动化买手实名核验网关
运维·人工智能·架构·自动化
天衍四九-3 小时前
Docker Compose企业实战系列(八·终章):多环境隔离实战,开发/测试/生产一键切换
运维·docker·容器