sticky bit 是目录权限位(1000),启用后仅文件所有者、目录所有者或root可删除或重命名目录内文件,防止多用户共享时误删他人文件,需配合o+x才生效(显示为小写t),对nfs和容器挂载无效。

sticky bit 是什么,为什么普通用户删不掉别人在共享目录里建的文件
linux 的 sticky bit 本质是个权限位(1000),加在目录上后,只允许文件所有者、目录所有者或 root 删除或重命名该目录下的文件——哪怕别人对目录有 w 权限也不行。这不是“防误删”的装饰功能,而是解决多用户协作时最基础的信任问题。
常见错误现象:rm: cannot remove 'xxx': Operation not permitted,但 ls -ld /shared 显示目录权限是 drwxrwxrwx,让人误以为“明明全开了写权限”。其实缺的就是那个末尾的 t(如 drwxrwxrwt)。
- 使用场景:/tmp、团队项目共享构建目录、CI 输出物暂存区这类多人可写但不可互删的路径
- 设置命令必须用八进制:
chmod 1777 /shared(1是 sticky bit,777是常规权限);用符号法容易漏:chmod +t /shared可以,但chmod o+t /shared才精准,避免意外改了其他位 - 注意:对文件设 sticky bit 没有效果(内核忽略),只对目录有意义
如何确认 sticky bit 是否生效,以及它和 chmod o+t 的关系
别信 ls -l 看到的 t 就万事大吉——那个 t 出现在权限串最后,前提是其他权限已满足“others 可执行”(即 o+x)。如果目录被设成 chmod 1776 /shared,ls 显示的是 T(大写),代表 sticky bit 已设但 o+x 缺失,此时它不生效。
- 正确检查方式:
stat /shared | grep "access:.*[0-9]t$"或直接看ls -ld /shared输出末位是否为小写t -
chmod o+t和chmod 1777效果等价,但前者更安全:它只翻转 sticky bit 位,不碰已有权限;后者会强制覆盖整个权限字,可能误关x位 - 兼容性无坑:从 2.4 内核至今,所有主流发行版行为一致,无需考虑 glibc 版本
sticky bit 在 NFS 或容器挂载目录中是否还起作用
不起作用——这是最容易被忽略的硬限制。NFS 服务端若没配 nohide 或导出选项含 insecure,客户端挂载后 sticky bit 位会被丢弃;容器场景更典型:宿主机目录加了 sticky bit,但用 docker run -v /host/shared:/container/shared 挂进去后,ls -ld /container/shared 显示的是 drwxrwxrwx(无 t),且删除权限完全由容器内 UID/GID 决定。
- NFS 方案:服务端
/etc/exports中对应路径必须显式加no_root_squash(不推荐)或确保客户端 UID 映射一致,否则 sticky bit 元数据根本传不过去 - 容器方案:sticky bit 必须在容器内设置,例如启动时用
docker run --init -v /host/shared:/shared alpine chmod 1777 /shared;或者用 initContainer 在 k8s 中预处理 - 性能影响:零。sticky bit 是 inode 层标记,不增加任何磁盘 I/O 或内存开销
为什么 /tmp 默认有 sticky bit,但你自己建的共享目录不能直接抄它的权限
/tmp 的 1777 是系统初始化脚本写的,但关键不在权限数字,而在它的属主和属组:root:root。如果你新建目录 chown nobody:nogroup /shared && chmod 1777 /shared,普通用户仍可能因 umask 或创建时继承问题绕过限制——比如用户用 touch /shared/file 创建文件后,文件属主是自己,但属组可能是 nogroup,这时同组其他人若对目录有 w 权限,就能删掉它(sticky bit 不拦组内删)。
- 真正安全的共享目录要满足三个条件:目录属主为可信管理员(如
root或专用服务账号)、属组为协作组(如devteam)、权限为1775(即drwxrwsr-x+ sticky) - 必须配合
setgid位(2):chmod 2775 /shared让新文件自动继承目录属组,再加 sticky bit 才形成闭环 - 别依赖 umask:用户 shell 的
umask 002只影响新建文件权限,不影响 sticky bit 生效逻辑
sticky bit 不是银弹。它只管“删/重命名”这一动作,对文件内容修改、读取、硬链接创建完全不管。真要防数据越界,得靠 SELinux 或 user namespaces 配合——但那是另一个问题了。