ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Linux用户、用户组与权限管理:从基础原理到实战排查

Linux用户、用户组与权限管理:从基础原理到实战排查 我先从我刚入行时一次差点酿成事故的经历说起。当时接手一台测试服务器需要在上面部署一套内部协作工具同事临时用 root 登录把/etc/下好几个配置文件的权限顺手改成了 777理由是“开发环境无所谓”。结果第二天团队里另外几个同学再登录时有的写不了配置有的连目录都进不去排查了一上午才发现是那次权限修改把整个系统的文件保护搞乱了。从那以后我算是彻底明白了一件事Linux 的用户、用户组和权限机制不是系统给你添麻烦的条条框框而是整个系统最核心的“保命设计”。这篇文章我就把用户和用户组管理、权限管理这些内容结合我实际踩过的坑系统地讲一遍希望能帮刚接触 Linux 的同学少走弯路也能让有基础的朋友把一些细节彻底理清。这篇内容适合所有在 Linux 上做开发、运维、测试或者自己折腾服务器的朋友无论你是刚装好一个 Ubuntu 虚拟机还是在公司机房管着一堆机器用户、用户组、权限这三个词都是绕不开的基本功。我会尽量用大白话把原理讲透再给出能直接复制的命令和步骤。1. 为什么用户与权限是 Linux 系统的“地基”1.1 一台多用户机器的秩序靠的是“人和身份”的划分Linux 从设计之初就是一套多用户、多任务的系统不像个人电脑那样通常只有一个人用。既然要容纳多个用户同时登录、同时跑程序就必须有一个机制来回答三个基本问题你是谁你能访问哪些东西你能对它们做什么用户账号解决前两个问题权限系统解决第三个问题。我常拿一个比喻来理解一台 Linux 服务器就像一栋写字楼每个用户是一张门禁卡用户组相当于楼层和部门的门禁分组规则而文件权限则是每扇门上的锁。你拿着自己的门禁卡能不能打开某个房间的门取决于你这张卡属于哪个部门以及门锁给这个部门开放了几级权限。这栋楼的物业管理员就是 root他可以配置所有门锁、发卡、销卡甚至直接砸门。理解了这层关系你就会明白权限管理不是“改个数字”那么随意它本质上是整个系统运作秩序的体现。把不该开的权限开了就像把财务室的门锁换成超市储物锁出事只是时间问题。1.2 UID、GID人的名字可以一样但身份证号不能一样在 Linux 眼里用户名的地位没有你想象的那么高。系统真正识别用户靠的是 UID用户 ID和 GID组 ID用户名只是给人类看的便于记忆的标签。你可以把 UID 想象成身份证号用户名想象成名字。在同一台机器上可以有重名的普通用户名吗不可以因为系统不允许创建重复的用户名。但即使两个不同的用户名没有重名如果它们的 UID 相同那么系统会认为这两个名字指向的是同一个“身份”。这就好比你有两个不同的别名但身份证号是同一个系统只认后者。查看一个用户的身份信息最常用的命令是id username输出大概是这样的uid1000(dev1) gid1000(dev1) groups1000(dev1),4(adm),27(sudo)这里面就能看到 UID、主组 GID 和附加组列表。我之前遇到过一个问题某用户被误删后重建用户名一样但 UID 变了结果这个用户原本拥有的文件全部变成了“无主文件”显示为数字 UID并且无法正常读写。这就是 UID 和用户名分离造成的经典麻烦后面会细说。1.3 root 用户权限大不意味着应该天天用Linux 里有个 UID 为 0 的特殊用户叫 root也就是超级管理员。root 可以无视所有文件权限、无视所有用户组的限制想干什么就干什么。这套设计保证了系统出问题时管理员一定能接管但也意味着 root 的每一次操作都可能是“致命一击”。现实中很多初学者为了图省事直接切到 root 操作一切这是非常危险的习惯。我自己早期就干过在 root 下用rm -rf加错路径的事还好不是生产环境不然后果不堪设想。正确做法是平时用普通用户工作需要特权时使用sudo命令临时提权这样系统会有操作日志而且能最大程度减少误操作的影响范围。2. 从零创建用户与用户组useradd/groupadd 的完整使用逻辑2.1 先建组还是先建用户顺序确实有讲究刚开始学 Linux 的人经常困惑创建一个用户之前是不是一定要先建一个同名的组其实不是当使用useradd创建新用户时默认行为是自动创建一个与用户名同名的私有组这个组里只有这个用户一个人。但在真实工作场景里我们更常遇到的需求是“让一批人共同访问某些资源”。这时候就应该先规划好用户组再创建用户或者把现有用户加入已有的组。一个好的习惯是先按业务或项目划分组再把用户放进去而不是每个人都用私有组然后在权限上孤立无援。例如我要给一个项目组 devops 创建用户常规做法是groupadd devops useradd -g devops -m -s /bin/bash -c DevOps Engineer dev1这条命令里-g devops指定了主组-m表示创建家目录-s指定登录 shell-c是注释说明。这样建出来的用户一出生就属于 devops 组后续给这个项目组授信时只需针对 devops 组操作即可。2.2 useradd 参数拆解每一项都是“需求映射”初学者看 useradd 参数容易一头雾水我习惯把参数按“身份、位置、使用方式”三个维度去记忆。身份相关的主要参数有参数含义实际用途-u指定 UID手动分配固定 ID方便备份、恢复或同步-g指定主组 GID决定用户文件默认属组-G指定附加组列表让用户同时属于多个组获得多个组权限-c注释说明这个账号是谁、干什么用的位置相关的参数-d可以指定家目录路径-m表示如果家目录不存在就创建-M表示不创建家目录比如创建纯服务账号时。使用方式相关的参数主要是-s指定登录 shell。如果不希望某个账号能登录系统可以给一个-s /usr/sbin/nologin很多系统服务账号就是这么创建的。举个例子创建一个用于运行 Web 服务的用户既不希望它登录也不想要家目录useradd -M -s /usr/sbin/nologin -c Nginx Web Server nginx-user这样创建的用户只能作为进程运行身份无法被远程或本地登录安全性高很多。2.3 修改和删除用户usermod、userdel 的正确姿势用户建好不等于一劳永逸员工调岗、离职账号权限都需要相应调整。修改用户信息最常用的命令是usermod。比如把 dev1 加入 sudo 附加组usermod -aG sudo dev1特别注意这里必须加-aappend它的意思是追加到附加组而不是把用户现有的附加组覆盖掉。如果漏了-a用户会从其他附加组中被移除这在生产环境是个很隐蔽的坑。锁定和解锁账号用-L和-Uusermod -L dev1 usermod -U dev1锁定的账号无法登录但数据还在。删除用户时userdel默认不删家目录如果确定要连家目录一起删要加-ruserdel -r dev1这里踩过坑的人会提醒你删除用户前务必确认这个用户在主目录里是否还有其他进程正在使用的文件否则容易出现“文件明明还在但所有者和组都变成数字”的尴尬情况。3. 权限位拆解rwx 与数字权限表背后的真实含义3.1 三段权限位文件所有者、组、其他用户在 Linux 里用ls -l查看文件详情时第一列是类似-rwxr-xr--的十位字符这是整个权限模型最直观的展示。第一位代表文件类型-是普通文件d是目录l是软链接等。后面九位分成三组每组三位分别代表文件所有者user、用户组group、其他人other的权限。每组三位按顺序是读r、写w、执行x。如果对应位置是-就表示没有这项权限。拿-rwxr-xr--来说所有者可以读、写、执行组内用户可以读、执行但不能写其他人只能读。我经常用一句话概括看权限的第一件事是确认你属于哪一个“身份分类”然后只看对应的那三位。3.2 目录的 rwx 是另外一套逻辑许多初学者在这里卡住为什么对一个目录给了某个用户r权限他还是进不去因为目录的权限语义和文件完全不同必须单独理解。在目录上读权限r可以列出目录下的文件名即ls能看到有哪些文件。写权限w可以在目录里创建、删除、重命名文件注意这个权限直接影响的是“目录内容本身”。执行权限x可以进入这个目录即cd进去以及访问里面文件的元信息。也就是说如果只给目录 r 权限没有 x用户能ls列出文件名但cd时会被拒绝访问里面的文件更是无从谈起。想要让用户能正常穿梭目录并访问文件至少需要同时有r和x而想要能在目录下创建和删除文件就需要w。我再举一个真实场景团队共享一个/data/project目录希望 devops 组的成员都能进入并创建文件但其他人只能进入查看。合理的权限配置是目录所有者是 dev1组是 devops权限设为rwxr-x---即750。这时 devops 组成员能进能写其他人连进入都做不到安全性和协作性都兼顾了。3.3 数字权限的计算原理Linux 提供了一个便捷的数字表达方式r4w2x1。每个身份段的权限值就是该段三个数字相加。权限组合二进制数字值表示含义---0000无任何权限--x0011仅可执行-w-0102仅可写-wx0113可写、可执行r--1004仅可读r-x1015可读、可执行rw-1106可读、可写rwx1117可读、可写、可执行所以750的含义就是所有者7rwx组5r-x其他人0---。644则是文件默认最常用的权限组合所有者可读写组和其他人只读。理解了数字计算方法后面写命令时就不需要死记硬背随手就能算出自己想要的组合。4. chmod/chown/chgrp 实战改权限时必须避开的坑4.1 chmod 的数字模式和符号模式修改文件权限chmod是最常用的命令支持两种模式。数字模式最直观chmod 750 /data/project这会把/data/project的权限直接设置为所有者 rwx、组 r-x、其他人无权限。符号模式则更适合局部调整比如只给脚本加上执行权限chmod ux /opt/app/run.sh chmod g-w /data/project/file.txt chmod or /data/project/notes.txt其中 u 表示所有者g 表示组o 表示其他人a 表示所有人。加号是添加权限减号是移除权限等号是精确设置权限。我在工作中更喜欢符号模式因为它能精确表达“我只想改哪一段”不会因为一个命令把整个权限冲掉。比如chmod ux只是在原有基础上加一个执行位而chmod 755则是把所有者、组、其他人的权限全部重新设置一遍。如果原本文件所有者权限里有你需要保留的其他属性数字模式可能造成误伤。4.2 chown 经常和 chmod 一起改但千万别用反了改完权限位另一个高频操作是改所有者和属组。chown负责改所有者chgrp可以单独改属组但更常见的是用一条chown同时修改两者chown dev1:devops /data/project这条命令把/data/project的所有者改成 dev1属组改成 devops。冒号前后是“所有者:属组”多用几次自然就记住了。如果需要递归修改目录下所有内容加-R参数chown -R dev1:devops /data/project此时务必意识到递归的后果整个目录树下所有文件的所有权和组关系都会被改变。如果只是想让某个文件被另一个用户访问逐个文件chown往往更安全。此外修改软链接自身的属主需要加-h参数否则默认修改的是链接指向的目标文件这是个容易被忽略的细节我第一次操作时还迷惑了好一阵子。4.3 --reference 参数以某个文件为模板同步权限有时候需要把一批文件的权限设成和某个参考文件一模一样这时不必一个个去算数字--reference参数特别好用。chmod --reference/data/template.txt /data/target.txt chown --reference/data/template.txt /data/target.txt这在批量发布配置文件场景里很实用先配置好一个“标准文件”的所有者和权限然后用 reference 同步给其他文件就不容易因为手输数字出错。我自己在管理一堆 Nginx 虚拟主机配置时就靠这个方法保证所有 conf 文件的权限和属主都一致。4.4 一个典型误操作案例递归 chmod 把整个应用搞挂我见过比较典型的误操作是某同事为了方便对整个项目目录执行了chmod -R 777 /app/project结果应用能跑了但风险也随之而来任何系统用户都能改里面的核心代码和配置。更尴尬的是有些 CGI 脚本要求权限不能是全局可写否则拒绝执行于是原本想省事反而多花了半天排查。正确的做法是给应用目录一个合理的权限基线比如目录755、文件644对需要运行的环境目录单独处理。需要写文件的地方用属组权限控制而不是把“其他用户”也一起放开。如果你确实需要批量调整建议先find找出目录和文件分别执行 chmodfind /app/project -type d -exec chmod 755 {} \; find /app/project -type f -exec chmod 644 {} \;这种做法的好处是目录和文件权限分开处理更符合实际需求也避免了 777 的无差别开放。5. SUID、SGID、Sticky Bit容易被忽略却决定系统安全的特殊权限位5.1 SUID临时“变身”的机制普通权限之外Linux 还支持三个特殊权限位。第一个是 SUIDSet User ID它作用在可执行文件上时效果非常特殊普通用户执行这个文件时进程的有效用户 ID 会临时变成文件所有者的 ID。最经典的例子是/usr/bin/passwd。普通用户修改自己的密码时需要写入/etc/shadow文件而这个文件只有 root 才能写。正常情况下普通用户根本不可能改密码但 passwd 程序文件带有 SUID 权限用户执行它时会临时以 root 身份运行所以才能完成写 shadow 操作。在ls -l中SUID 位体现在所有者执行位上如果是s说明 SUID 生效如果是S说明设置了但所有者本身没有执行权限此时 SUID 不生效。给文件设置 SUID 的命令chmod us /path/to/fileSUID 是一把双刃剑不合理的 SUID 是系统安全重大隐患。如果某个普通用户可以执行的脚本文件带 SUID 且所有者是 root那几乎等于把 root 权限拱手送人。我建议对系统里所有 SUID 文件定期排查至少心里有数。5.2 SGID让目录协作不再“串门”到错误的分组SGID 和 SUID 类似但它作用在组上而且对目录特别有意义。当 SGID 设置在一个可执行文件上时用户执行时临时获得文件属组的权限。但更有价值的是把 SGID 设置在目录上任何用户在目录下创建的新文件、新目录它们的属组会自动继承目录的属组而不是创建者自己的私有组。这个特性在团队共享目录里极为好用。比如/data/project属组是 devops并设置了 SGID那么 devops 组内任何成员在里面创建文件文件属组都会自动是 devops其他人在 devops 组内就可以按组权限协作处理文件而不会因为“这文件是我建的组却是我的私有组”而导致团队其他成员无法编辑。设置 SGIDchmod gs /data/project在ls -l里表现为组执行位上的s。我实际维护的协作目录几乎都会加 SGID因为这一条命令解决了协作场景里最麻烦的“组归属”问题。不过要配合合理的组权限使用否则新文件默认权限如果其他用户不可访问依然会出问题。5.3 Sticky Bit保护 /tmp 的“最后一道防线”第三个特殊权限位是 Sticky Bit粘滞位现在主要用于目录。它有一个非常直观的特性即使目录是全局可写比如 /tmp但只要设置了粘滞位用户就只能删除或重命名属于自己的文件不能动别人的文件。/tmp 目录就是典型例子它的权限是drwxrwxrwt最后的t就是 Sticky Bit。因为 /tmp 对所有人可写如果没有粘滞位任何人能随意删除其他用户临时文件那整个临时目录就乱套了。给目录设置粘滞位chmod t /tmp在ls -l中表现为其他人执行位上的t。这个权限位在管理共享临时目录时非常实用比如项目里的共享上传目录rwxrwxrwt权限用户能写文件但只能删自己的文件。特殊权限位用数字表示时SUID4SGID2Sticky1加在普通权限前面比如chmod 1777 /tmp就是设置粘滞位的同时所有人可读写执行。但不建议随手用数字因为太容易和普通权限位搞混我更喜欢分别用us、gs、t这种符号模式可读性高得多。6. Permission denied 排查链路一个运维老手的完整定位流程6.1 先从三个维度定位“被拒”的真实原因在 Linux 下干活几乎人人都会遇到Permission denied。新手的反应往往是直接chmod 777这是最要不得的。正确做法是按我下面这套链路逐层分析。收到 Permission denied 后第一件事是确认当前你是谁id接着确认目标文件或目录的所有者和权限属性ls -ld /path/to/project ls -l /path/to/project此时就能判断你这边的身份属于文件权限里的哪一段对应的 rwx 是什么。如果目标文件的路径跨目录中间每一步目录权限也会影响最终访问这时可以用namei命令查看路径每一层的权限情况namei -l /var/www/html/index.htmlnamei会列出路径上每一层目录及文件的所有者、权限很多权限问题实际上出在中间某一层目录的 x 权限缺失上而不是目标文件本身。这种问题如果没有namei排查起来会非常折磨人。6.2 文件写不进、目录进不去、程序跑不起来分别怎么处理常见问题我归纳成三类第一类文件能读不能写。通常是文件对当前身份没有 w 权限或者文件所属目录没有 w 权限要删除/重命名文件需要目录写权限。此时先想清楚你要做的是写文件内容还是改文件名和删除文件。前者改文件权限后者改目录权限。第二类目录进不去或ls没输出。多半是目录的 x 权限缺失或者当前身份既不是所有者也不在属组里而 other 段的权限是---。此时考虑用chmod gx或者把用户加入对应组。第三类程序启动时报权限错误。除了普通权限外还要考虑文件所有者和属组是否正确、是否有 SUID/SGID、SELinux/AppArmor 等安全模块的干预。如果临时测试发现setenforce 0后能跑说明很可能是 SELinux 上下文问题需要重新打标签而不是粗暴关掉 SELinux。6.3 ACL 和 sudo比简单权限位更细粒度的控制方式有些场景下普通权限位不够用比如“同一个目录里的某个子文件只允许特定用户读其他人不能读”用传统 chmod 很难优雅实现。这时可以用 ACL访问控制列表精细控制setfacl -m u:dev1:rx /data/project/special-file getfacl /data/project/special-filesetfacl能针对指定用户、指定组设置权限比传统 rwx 三段位灵活得多。配置好 ACL 后ls -l的权限位末尾会出现一个号提醒此文件有扩展 ACL。不要小看这个加号如果用chmod修改基本权限ACL 可能随之变化必要时需要重新setfacl。sudo 的权限控制也是日常绕不开的。查看当前用户能执行哪些 sudo 命令sudo -l编辑 sudo 权限需要修改/etc/sudoers但强烈建议不要直接编辑这个文件而是使用visudovisudo会在保存前做语法检查能防止写错配置导致 root 都无法提权的严重事故。给某个用户组添加 sudo 权限的典型写法%devops ALL(ALL) NOPASSWD: /usr/bin/systemctl这行表示 devops 组成员在使用 systemctl 时可以免密并提权。把 sudo 权限限制到命令级别比直接给 ALL 安全得多这是我实践中最推荐的做法。6.4 文件属主突然变成数字多半是用户被删了最后再说一个非常多见的现象某个文件用ls -l查看时所有者显示为数字而不是用户名。这不是系统出 bug而是因为文件对应的 UID 在系统里不存在了常见原因是那个用户被userdel删除了但文件还留在磁盘上。处理思路很简单重新创建相同 UID 的用户或者用chown把文件归属到现存用户。useradd -u 1005 -M -s /usr/sbin/nologin olduser chown -R olduser:olduser /data/leftover这里我建议先查清楚这个 UID 原来属于谁再决定归属否则可能把别人历史的文件全部划给一个新用户。7. 实操总结与经验延伸写到这里其实已经把 Linux 用户、用户组、权限管理的主要脉络捋完了。回看我自己的经历真正让我对这套机制产生敬畏心的不是某个高深技巧而是几次权限误操作带来的教训。其中最深刻的一条是在批量执行 chmod 和 chown 之前永远先看一眼当前路径、确认操作范围和目标身份切勿在 root 下靠“肌肉记忆”敲命令。日常使用中我养成了几个小习惯在这里分享给大家创建用户时尽量用-c参数写上用途和负责人不然半年后没人记得这个账号是谁建的。能用附加组解决的需求就不要反复修改用户的主组避免文件属主追踪变得混乱。目录协作至少设置 SGID能省掉很多组归属问题。权限问题定位优先用namei和getfacl比瞎猜高效得多。谨慎对待 777能不开就不开实在需要临时开也要记得用完后恢复。这篇文章覆盖了用户和用户组管理、权限位计算、chmod 和 chown 实战、特殊权限位 SUID/SGID/Sticky Bit以及一套完整的 Permission denied 排查思路。看完之后建议你找一台虚拟机从创建新用户开始到设置共享目录、再模拟一次权限报错把这套流程完整走一遍。只有亲手操作过这些命令和权限组合才会真正长在你身上遇到问题时不慌不乱直接定位到根因。
返回列表