
最近在整理Linux学习材料翻到一份标注着“1.21”的权限管理笔记有些细节差点想不起来。今天干脆把角色和权限这整块内容重新过一遍按照自己实际排查问题的顺序把用户、组、文件权限、ACL、sudo这几件事串起来讲透。这篇文章没有教科书式的术语轰炸更多是操作层面的心得包括那些踩过坑之后才明白的细节。适合刚学Linux的初学者也适合已经用过一段时间但想系统补一补权限知识的人。Linux的权限管理看起来就几个命令但真正用好的前提是理解“角色”这个词到底指什么。用户、组、其他人这三层身份再加上文件的读、写、执行三种权限组合起来就是一套完整的安全模型。我见过很多新手卡在“我明明把文件放到了某个目录别人还是看不到”这种问题上说到底还是没把角色和权限的关系理顺。这篇笔记就按我自己的学习路径来写先说角色怎么持久化再说文件权限怎么调整最后补上ACL和sudo这两个实战利器。1. 权限管理在Linux系统中的位置先理解“角色”是什么1.1 为什么权限管理总是从“用户和组”讲起Linux是一个多用户操作系统同一台机器上可能有多个开发者、多个服务账号在同时使用。如果所有人都能改所有文件那系统基本就失控了。所以内核给每个进程和文件都打上了身份标签这个标签就是UID用户ID和GID组ID。文件权限检查时内核会先看当前进程属于哪个用户、哪些组再根据文件的属主、属组、其他人三个维度去比对最终决定放行还是拒绝。这里要强调一个习惯不要把“用户”和“人”等同起来。Linux里凡是要运行一个程序、占用一个资源都需要有对应的用户身份。很多后台服务比如数据库、Web服务器都会单独创建一套系统账号来运行这样即使某个服务被攻破攻击者也只拿到低权限的系统账号而不是root。这就是权限管理里“最小权限原则”的落地。我一开始也觉得创建一堆用户很麻烦但经历过一次因为用root跑服务而导致配置被误改的事故后就老实了。1.2 文件权限位rwx与ugo怎么对应到具体操作用ls -l看任何一个文件第一列是类似-rw-r--r--的一串字符。这串字符分成四组第一个字符是文件类型后面每三个字符一组分别表示属主u、属组g、其他o的权限。三组里的字符就是 r读、w写、x执行没有权限的位置显示为-。r对普通文件来说决定你能不能读取文件内容对目录来说决定你能不能列出目录里的文件名也就是能不能用ls。w对普通文件来说决定你能不能修改文件内容对目录来说决定你能不能在该目录里新建文件、删除文件、重命名文件。x对普通文件来说决定你能不能把它当作程序来运行对目录来说决定你能不能进入这个目录也就是能不能用cd或者是否能访问目录里文件的元信息。这里最容易被忽略的是目录的权限。很多新手以为只要给了文件本身的权限就能自由操作实际上你在访问文件之前路径上的每一个目录都要有对应的执行权限。比如/data/app/config.ini这个文件哪怕文件权限是rw-r--r--但/data目录没有 x 权限你一样无法读取。这个坑在配置完新目录后尤其常见。2. 角色管理的核心操作用户与组的增删改查2.1 用户管理useradd、usermod、passwd、userdel创建用户最常用的是useradd但不同发行版默认参数不一样所以别只靠裸命令。我习惯这样用useradd -m -s /bin/bash -u 2001 -G wheel devuser-m自动创建家目录并拷贝骨架文件。-s指定默认Shell比如/bin/bash。-u指定UID如果提供服务的程序有特殊要求比如需要映射NFS共享里的文件属主固定UID会省很多事。-G指定附加组用逗号分隔。比如把用户加入wheel组是为了让它能使用sudo。创建后马上设密码passwd devuser交互式输入两次即可。如果你在脚本里需要非交互设置可以用echo devuser:123456 | chpasswd但用明文在命令行里敲密码始终有风险生产环境建议用openssl passwd -6 hash生成加密后的密码串再通过useradd -p传入。修改用户用usermod常用场景是改附加组、改登录Shell、改家目录。比如把用户从一个组里移除又加入另一个组usermod -G groupA,groupB devuser特别提醒usermod -G后面如果只写一个组会把该用户的附加组列表整个替换成这一个组。原先进了哪些组你得自己先id devuser查好再拼进去。删除用户时userdel -r devuser会连带删除家目录和邮件池但程序运行时产生的临时文件不一定能删干净所以删除前最好备份该用户的重要数据。2.2 组管理groupadd、groupmod、groupdel、gpasswd组的创建很简单groupadd -g 2001 devgroup。组的作用主要是把若干个用户聚合起来让它们共享一组权限。修改组名用groupmod -n newname oldname删除空组用groupdel如果组里还有用户作为“主组”删除会报错需要先把用户的gid改到其他组。把用户加入组时我优先推荐gpasswd而不是直接改/etc/groupgpasswd -a devuser devgroup gpasswd -d devuser devgroupgpasswd -a是把用户追加到组里不会影响该用户其他附加组比usermod -G安全得多。另外-a后面的参数顺序别反了我犯过错gpasswd -a devgroup devuser会把devgroup这个用户加入devuser这个组系统不报错但逻辑全反了。2.3 角色管理必须养成的三个好习惯第一查看用户和组的最终状态用id命令它会一次性列出UID、主组、附加组比看/etc/passwd和/etc/group直观。第二新用户默认的umask值会影响后续创建文件和目录的初始权限如果不希望用户之间默认互相可见文件可以在/etc/bashrc里调整 umask。第三定期清理长期不用的系统账号。很多安全问题不是从root被攻破的而是因为某个一直挂着SSH登录的闲置账号被爆破成功。另外/etc/login.defs里的CREATE_HOME、UMASK、PASS_MAX_DAYS这些参数会影响useradd的默认行为属于“全局默认配置”。如果你发现不同版本Linux上useradd -m的效果不一样多半是这里设置不同。我曾经在两台机器上建用户一台自动建了家目录一台没有排查半天才发现是发行版默认配置的差异。3. 权限管理的核心操作文件与目录的rwx调整3.1 看懂 ls -l 输出里的每个字段ls -l是权限管理的第一工具。拿一行实际输出来说-rw-r--r-- 1 root root 1024 Apr 10 10:00 app.conf-rw-r--r--第一字符-表示普通文件接下来三组是权限。1硬链接数。对目录来说这个数字表示子目录数2。root root第一个是属主第二个是属组。1024文件大小。Apr 10 10:00最后修改时间。app.conf文件名。看这串输出就能确认一件事app.conf对root是读写权限对root这个组是读权限其他用户也是读权限。要真正理解权限状态建议多练习用ls -l /tmp、ls -ld /tmp区分文件和目录。ls -ld是查看目录本身的权限而不是目录里的内容。3.2 chmod的两种模式符号模式与数字模式哪个更好用chmod支持符号模式和数字模式。符号模式直观适合精确修改某个身份chmod ux script.sh chmod g-w,o-r data.txt chmod ar readme.md数字模式适合批量设置完整权限每一位代表一组权限的和r4w2x1。chmod 750 script.sh就是属主 rwx属组 r-x其他无权限。我个人的习惯是新增文件时用数字模式直接给一个明确的结果比如chmod 644 file、chmod 755 dir在原有基础上微调时用符号模式比如临时给其他用户加上执行权限用chmod ox比chmod 755更不会误伤其他位的权限。特别提醒一下给目录递归设置权限时别乱用chmod -R 777。如果应用确实需要写权限应该只给特定的属组或者用ACL而不是一刀切放给所有人。这一点在Web目录里尤其重要我曾经见过站点上传目录被改成777后被人放了恶意脚本整台机器被搅得鸡飞狗跳。3.3 修改属主和属组chown与chgrp的先后顺序把文件的属主改为某个用户同时把属组改为某个组chown devuser:devgroup file.txt如果只想改属组可以用chgrp devgroup file.txt或者chown :devgroup file.txt。这里有个小细节chown user和chown user:group中间不要加空格不然会变成两个参数带来不了预期效果。递归修改目录属主时我建议先改属组再改属主或者一条命令搞定因为你如果先chown -R user dir再chgrp -R group dir中间会出现一小段时间内目录属主是user但属组还是旧组的状态在某些自动同步脚本里会漏读文件。直接这样写最稳chown -R user:group /data/service3.4 特殊权限位SUID、SGID、Sticky Bit除了rwxLinux还有三个特殊权限位分别对应数字4、2、1放在权限数字的前面。SUID4作用于可执行文件。它会让进程以文件属主的身份运行而不是执行者身份。最典型的例子是passwd它需要修改/etc/shadow但普通用户又没有该文件的写权限所以passwd程序设置了SUID执行时临时提升为root权限。SGID2作用于可执行文件时进程会继承文件属组的身份作用于目录时会让该目录下新建的文件自动继承目录的属组而不用每人都改自己的主组。Sticky Bit1作用于目录限制删除权限。只在目录属主、文件属主或root可以删除文件。比如/tmp默认是drwxrwxrwt所有人都能往里面写文件但A用户不能删B用户创建的文件。设置方式chmod us file、chmod gs dir、chmod t dir或者数字方式chmod 4755 file、chmod 2770 dir、chmod 1777 /tmp。查看特殊位时ls -l的小写字母会变成s、S、t、T。如果看到大写的S或T说明对应位置没有x权限也就是说特殊权限虽然有设置但不生效这时候要回头检查是不是漏了执行权限。4. 权限管理的进阶ACL与sudo的实用姿势4.1 ACL给某个用户单独开权限的细粒度方案传统的ugo权限只能给“属主”、“属组”、“其他人”三类角色设定权限。但实际工作中经常出现这样的需求某个文件属于appuser但需要让另一个backupuser对其具有只读权限同时其他用户仍然无权访问。这种情况下要么把backupuser加进文件属组要么就得用ACL。先给文件系统挂载参数里确认支持ACL绝大多数Linux发行版默认支持然后设置setfacl -m u:backupuser:r /data/app/config.ini查看文件的ACL记录getfacl /data/app/config.ini如果想把这个用户的所有权限收回setfacl -x u:backupuser /data/app/config.ini如果想把整个文件上的ACL全部清掉setfacl -b /data/app/config.iniACL设置后在ls -l输出中权限位末尾会出现一个号提醒你这文件有ACL扩展项。别忽略这个加号它表示同一类身份可能还有额外授权。有一次我在一个目录下拷贝文件后发现新文件被自动带上了ACL原因就是目录设置了默认ACL。默认ACL用setfacl -d -m u:someone:rx /data/dir设置其效果是新创建的文件会自动继承这些ACL规则。4.2 sudo给普通用户开“可控的root权限”sudo是权限管理里最常用的提权入口。它通过/etc/sudoers用visudo编辑控制谁能在哪些主机上、以哪个身份、执行哪些命令。一个典型配置devuser ALL(ALL) NOPASSWD: /usr/bin/systemctl restart nginx这段配置的意思是devuser可以在任何主机上不输入密码执行重启nginx的命令。这里要注意必须写命令的绝对路径否则可能留下安全隐患。查看命令路径用whichwhich systemctl如果想让某个组的所有成员都能执行shutdown命令可以把用户名改成%wheel。更安全的是定义命令别名Cmnd_Alias MANAGE_WEB /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx devuser ALL(ALL) MANAGE_WEBsudo还有一个细节执行sudo -u otheruser command可以以其他用户身份执行命令这在调试权限问题时非常有用。比如怀疑某个进程读不了配置文件就可以用这个命令模拟那个用户的视角去读文件sudo -u appuser cat /data/app/config.ini如果输出权限不足那就说明文件或目录权限有问题这个操作比看日志猜原因高效得多。5. 常见问题与排查实录我在权限上踩过的坑5.1 明明对文件有r权限程序还是说“Permission denied”遇到这种问题先别急着怀疑文件权限错了路径上每一个目录的x权限都要检查。执行namei -l /data/app/config.ini它会一层层列出路径上所有组件的权限。如果中间某个目录的other没有x权限那文件权限再好也没用。另一种可能是SELinux或AppArmor在拦你。如果在CentOS系机器上用ls -Z看system_u:object_r:httpd_sys_content_t这类上下文标签然后根据自己的进程类型设置正确标签比如chcon -t httpd_sys_content_t /data/www/index.html。5.2 自己有目录的w权限删除文件却报错这个坑非常经典。删除文件需要目录的w和x权限和文件本身的权限关系不大。但如果你直接对某个文件有w权限只能改它内容不能删它文件名。当目录上设置了Sticky Bit时即使你对目录有写权限也不能删除不属于你的文件。我曾在/tmp目录里清理其他用户遗留文件怎么删都不行后来才想起来Sticky Bit的作用。解决办法是先用ls -ld /tmp确认权限位末位是不是t如果是就只能让文件属主、目录属主或root来删。5.3 误改权限导致服务启动失败有一次我习惯性chown -R root:root /data/app结果那个应用是以appuser身份运行的紧接着服务就起不来了。启动失败的原因多半是应用没有权限读取自己的配置目录或者无法在数据目录里写日志。排查命令是sudo -u appuser test -r /data/app/config.ini; echo $?如果返回非0说明读不了。逐层检查目录权限最终定位到/data目录被改成了750而appuser不在root组里所以连进入/data的x权限都没有。遇到这种误改要一层层把属主和权限改回去先chown -R appuser:appgroup /data/app再给必要的目录设置gx最后启动服务验证。5.4 批量修改权限时如何避免殃及无辜批量操作时find配合chmod、chown是标准答案但一定不要无脑chmod -R 777。我常用的思路是先统计当前权限分布再分类处理。比如把/data/www下所有目录设为755、所有文件设为644find /data/www -type d -exec chmod 755 {} \; find /data/www -type f -exec chmod 644 {} \;注意find和exec之间的空格以及结尾的{} \;是必须的。更高效一点的方式是find /data/www -type d -exec chmod 755 {} 用结尾可以一次传多个路径给chmod减少fork次数在文件数量很大时能明显加快。批量修改属主时同理find /data/www -exec chown wwwuser:wwwgroup {} 如果要对包含特殊字符的文件名操作find -print0配xargs -0更安全但一般场景exec已经够用。结尾我个人在实际排查中最大的体会是权限管理不是把命令背熟就可以而是要在脑海里建立一个“角色 文件路径 进程身份”的三角模型。每一条权限问题最终都要落到“哪个进程以哪个身份去访问哪个路径”上。所以我现在排查时第一件事永远是执行id与ls -ld把角色和路径权限先钉在眼前再判断是直接调chmod还是改用户组或者补一条ACL。最后再分享一个小技巧给自己维护的机器写一个简单的权限巡检脚本定时跑一下把/etc/passwd、/etc/group、sudoers和关键服务目录的权限快照保存下来一旦出问题就能快速比对哪里被改动了。Linux权限管理的东西说多不多说少也不少但只要把基础的角色划分和rwx机制吃透后面遇到ACL、SELinux这些进阶概念都不会觉得难因为它们都是在解决同一个问题让每个程序只拥有它该有的那部分能力。