ARTICLE DETAIL

资讯详情

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

Linux账号权限管理从入门到实战:rwx、sudo与权限故障排查指南

Linux账号权限管理从入门到实战:rwx、sudo与权限故障排查指南 做Linux运维这些年账号和权限管理一直是我眼里最基础也最容易被忽视的一块。你可能会背一堆linux常用命令却不知道每个文件和目录背后那串rwx到底在说什么你也可能因为一次“无权限删除”、一个docker权限错误被迫在群里求助。这篇文章从账号体系、文件权限、sudo提权、故障修复四个方向把我这些年实际操作中的经验和教训完整捋一遍适合刚接触Linux的初学者也适合带过线上环境的运维和开发拿来查漏补缺。很多人觉得Linux账号权限就是“useradd加个用户chmod改个数字”真遇到问题才发现没那么简单。我自己就吃过两次大亏一次误把/home目录chmod -R 777导致同服务器上其他项目的数据全部暴露另一次给测试机配了弱密码被扫到后直接拖库。所以这篇文章我不想只罗列命令而是把每个操作背后的原理和坑都讲清楚。1. 账号管理的核心思路与初始配置1.1 用户账号体系拆解从 /etc/passwd 说起Linux下所有用户信息都存在/etc/passwd文件里这个文件每行代表一个账号冒号分隔成7个字段。我们拿cat /etc/passwd的输出举例root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin deploy:x:1001:1002:deploy user:/home/deploy:/bin/bash第1个字段是用户名第2个字段是密码占位符真正的密码在/etc/shadow里第3个是UID第4个是GID第5个是账号描述信息第6个是家目录最后一个是登录Shell。这里有个关键点不用怀疑passwd文件里显示x不代表这个用户没有密码而是表示密码被“影子化”到 shadow 文件了这样普通用户就看不到密码哈希了。UID的分配规则需要掌握0 是 root1-999 一般是系统账号发行版不同会有差异1000 及以上是普通用户。系统账号通常不能登录shell 被设置成/usr/sbin/nologin或/bin/false这样即使知道密码也无法登入。如果创建一个服务账号比如跑 nginx、跑 Java 应用建议useradd -r创建系统账号避免占用普通用户的UID区间。还有一个细节/etc/passwd文件本身必须是全局可读的因为很多程序需要通过 UID 查用户名。如果因为手抖把/etc/passwd权限改成 600你会发现系统里的ls -l都开始显示数字部分服务直接起不来。这就是为什么我下面会在“权限修复”里重点讲这个文件。1.2 创建账号的正确姿势useradd 背后做了什么新手用useradd最常见的错误是执行完useradd test后就以为完事了结果用su test登录后连家目录都没有。原因很简单useradd默认不会自动创建家目录不同发行版默认行为不一样Debian系用adduser会创建RedHat系用useradd会创建。为了行为可控我建议始终显式指定参数useradd -m -d /home/deploy -s /bin/bash -u 1001 -g 1002 deploy-m强制创建家目录-d指定家目录路径-s指定登录 Shell-u指定UID-g指定主用户组GID执行完之后必须用passwd deploy设置密码否则账号处于锁定状态无法登录。passwd命令写入的是/etc/shadow如果你用cat /etc/shadow能看到deploy:!!:...代表密码还没设置如果看到$6$...说明已经设置好了$6$开头是 SHA-512 加密的哈希。创建账号时我习惯记一个清单是否需要家目录如果只是跑服务可以用-r创建系统账号不建家目录主组选什么一般建一个同名的组或者直接加入已有业务组多久改一次密码可以配合chage命令设置过期策略比如chage -M 90代表90天后强制修改。实际上很多运维事故不是“不能创建账号”而是创建账号时没有规划好属组和家目录的权限。比如你创建一个叫git的用户但家目录所在的分区挂载了noexec选项后面想部署代码就跑不起来。这种情况排查起来比建账号本身麻烦得多。1.3 用户组管理让权限管理更高效用户组的意义在于把“授权”和“单个用户”解耦。假设有三个同事需要部署代码你不想逐个给/var/www/html写权限那就建一个deploy组把目录属组改成deploy并设置组写权限再把三个用户都加入deploy组。组相关的命令有三个groupadd创建组groupmod修改组属性groupdel删除组。给已有用户追加附加组时务必使用-a选项usermod -aG deploy zhangsan注意这里的-a别漏。如果写成usermod -G deploy zhangsan会把用户原先的附加组全部清空只保留deploy。这个坑我踩过当时一个用户本来有docker、sudo两个附加组为了给他加测试组执行完usermod -G test后他立刻失去了sudo权限线上变更也执行不了了。要是用usermod -aG test就不会出这个问题。查看一个用户所在的所有组用groups username或id username。id更直观第一行会显示 UID 和所有 GID。如果遇到用户明明加入docker组了执行docker ps仍然报权限错误90%的概率是当前 shell 会话没有重新加载组的缓存。解决办法是su - username重新登录或者干脆退出再登录一次而不是继续怀疑系统没生效。组的另一个应用场景是设定“共享目录”。比如/data/project目录想让组内成员都有读写权可以把它属组改成project然后chmod 2770 /data/project后面的2是 setgid 特殊权限位表示新创建的文件自动继承目录属组。这个机制我会在下一节展开。2. 文件权限机制深度拆解2.1 权限位的含义与rwx的底层逻辑用ls -l查看文件第一列比如drwxr-xr-x这10个字符拆开看第1位文件类型d目录、-普通文件、l符号链接、b块设备、c字符设备。第2-4位属主权限u。第5-7位属组权限g。第8-10位其他用户权限o。rwx对应数字分别取4、2、1所以rwxr-xr-x等于数字权限755。但这只是表面不同文件类型的含义完全不同。对于普通文件r能读w能写x能执行。对于目录r能列出目录里面有哪些文件w能在这目录下创建、删除文件x能进入目录或用完整路径访问目录内的文件。这里有个新手经常犯迷糊的点删除一个文件看的不是这个文件自身的权限而是它所在目录的写权限。比如有个文件/tmp/abc.txt权限是666你作为普通用户想删它只要你有/tmp目录的写权限就能删除跟文件自己的权限没关系。如果目录权限是555只读执行那文件权限哪怕777你也删不掉。另一个实践是设置目录权限时一定要给x权限否则目录打不开。常见的755目录代表属主全权限属组和其他人能读执行可以进入目录但不能创建或删除文件。664是文件的常见配置属主和属组可读写其他人只读。性能和安全之间需要平衡。我见过很多人图省事所有目录直接777当时是方便了之后出一次数据泄露就是灾难。相反如果所有文件都600、所有目录都700那协作起来也会很难受。合理的取舍是默认情况下程序文件用755业务数据用640密钥类文件用600。2.2 特殊权限位setuid、setgid与粘滞位除了普通rwxLinux还提供三个特殊权限位有时候它们制造的坑比普通权限更大。第一个是 setuid用数字表示为4比如chmod 4755 file。它的作用是进程执行这个文件时会临时获得文件属主的身份。最典型的例子是/usr/bin/passwd普通用户需要修改/etc/shadow但它自己没有权限所以 passwd 文件设置了-rwsr-xr-x执行时有效用户ID变成 root才能写入 shadow 文件。如果某个二进制被发现有 setuid 漏洞攻击者就能提权。隐患排查时用find / -perm -4000 2/dev/null找出所有 setuid 文件看看有没有可疑对象。第二个是 setgid用数字表示为2比如chmod 2770 /data/project。对目录设置 setgid 后在这个目录内新建的文件或子目录会自动继承该目录的属组而不是创建者的主组。共享团队目录建议都这么配省得每次都要chgrp。对文件设置 setgid则进程会临时获得文件属组身份这类场景比较少见。第三个是粘滞位用数字表示为1最典型的是/tmp目录权限1777。目录开启粘滞位后只有文件属主、目录属主或 root 才能删除目录里的文件否则即使目录有写权限普通用户也不能动不动就删别人的临时文件。chmod 1777 /tmp或chmod t /tmp都可以生效。这三个特殊权限位的排查优先级很高。线上环境如果出现“明明进不去目录但 setgid 导致新文件归属错误”多半就是这些位配错了。我的经验是特殊权限位不要随便用尤其是 setuid能用 sudo 提权解决的就不要搞 setuid。2.3 umask 如何影响新文件权限umask是一项登录就生效的属性它决定你新建文件和目录的默认权限。这个命令被很多人忽略但它直接决定后面是否会出现“创建的文件旁边的人读不了”或者“创建的文件权限过大”的问题。umask的规则是文件默认权限 666 与 umask 的补码做按位与目录默认权限 777 与 umask 的补码做按位与。为了好记可以近似认为是“用最大值减去 umask 的每一位”但注意只有“按位与”才是严谨的。比如 umask 是022文件666 (~022) 644目录777 (~022) 755如果 umask 是027文件666 (~027) 640目录777 (~027) 750umask 022是绝大多数发行版的默认值所以新建文件是644新建目录是755。一些安全要求高的环境会把 umask 设成077这样新文件默认600新目录默认700这会防止同台机器的其他用户看到你的文件但也意味着共享目录需要手动chmod调整。修改 umask 的位置一般是/etc/profile、/etc/bashrc或者用户自己的~/.bashrc。它影响的范围不仅仅是你手动创建的文件还有程序运行时自动生成的xxx.pid、日志文件等。如果你发现程序刚生成的日志其他用户读不了先看一眼这个进程启动时的 umask 是什么。我建议普通开发机保持022服务器上如果有多人协作可以配合 ACL 来精确控制而不是粗暴地把 umask 改成077。后面我会单独说 ACL 的用法。3. 实操从普通用户到sudo提权的最佳实践3.1 sudoers配置要点生产环境最忌讳用 root 到处跑。但完全不提升权也干不成活所以 sudo 是介于普通用户和 root 之间的桥梁。sudo的配置文件是/etc/sudoers修改它必须用专门命令visudo为什么不能用vim直接改因为visudo做了语法检查配置写错会提示你“有语法错误”不会让你保存后退出。改坏 sudoers 的后果很严重所有 sudo 命令都无法执行无法提权修复。如果真遇到了唯一的补救办法是启动到单用户模式或者在物理控制台用 root 登录后恢复。sudoers 的完整行格式是用户 主机列表(可以切换的身份) 命令列表比如devops ALL(ALL) ALL deploy ALL(ALL) /usr/bin/systemctl restart nginx第一行表示devops组注意前面有%表示组这里写成%devops更准确可以在任何主机上以任何身份执行任何命令。第二行表示deploy用户只能执行systemctl restart nginx这一条命令其他命令都会被拒。配置时必须注意命令列表里的二进制要用绝对路径否则会被拦截不要把ALL的权限给到非信任用户否则“最小权限原则”就失效了。我见过有人给不够信任的账号配了ALL ALL(ALL) ALL结果这个人删库跑路根本控制不住。这里还有一个隐蔽坑如果你在 sudoers 里同时配置了别名User_Alias、Cmnd_Alias别名名称必须由大写字母开头名称冲突也会导致校验失败。写完后建议用sudo -l查看当前用户可以执行的命令列表验证配置是否生效。3.2 用户切换的正确姿势先区分几个容易混的命令su切换到另一个用户但不加载对方的环境变量。su -切换用户并且重新加载对方的环境变量。sudo -i以 root 身份登录一个交互shell也会加载 root 的环境变量。sudo su -先提权到 root再切换 root 的 shell环境实际上和sudo -i类似但不标准。日常使用中su和su -的区别最要命。你想切到test用户查看它的 PATH 和家目录用了su test结果环境变量还是原来用户的跑java -version可能报找不到命令。加上-su - test后才会完整加载 test 用户的.bashrc、.profile此时 PATH 才是 test 自己的。还有一个安全细节su切换到 root 时需要输入 root 密码sudo只需要输入当前用户的密码。所以你要是想放开普通用户临时提权用 sudo 更方便。但如果你给某个用户开放了sudo ALL等于给了他 root 权限只是形式上多了一次密码校验。我在线上环境的实践是root 密码只有两台跳板机的负责人知道其余同事一律通过个人账号 sudo 白名单方式操作禁止su到 root禁止sudo su。这样所有操作都能在/var/log/secure里留下审计轨迹出了问题能查到是谁在什么时间执行了什么命令。3.3 批量创建用户的脚本示例遇到需要批量创建账号的场景比如新环境迁移、第二批员工入职手工useradd会疯掉。我一般写一段简单脚本处理#!/bin/bash # 批量创建用户密码统一从文件读取 # user_list.txt 格式用户名 初始密码 while read user pass; do useradd -m -s /bin/bash $user echo $user:$pass | chpasswd done user_list.txt脚本有两个关键点第一chpasswd是从标准输入读取用户名:密码并写入 shadow 文件比passwd适合批处理第二密码文件必须设置为只有 root 可读临时文件用完就删。如果要对不同用户设置不同组可以在循环里加上-g参数也可以先读一个组文件。我建议在脚本里增加判断逻辑比如用户已存在则跳过if id $user /dev/null; then echo user $user already exists, skip continue fi线上跑批量脚本前我先针对一条数据试运行确认创建出的账号权限、家目录归属都正确。不然一次性创建50个错误账号后面修起来不仅费时还容易引发权限混乱。4. 常见权限问题排查与修复实录4.1 “权限不足”类问题排查套路遇到任何Permission denied我按下面顺序排查ls -ld 目标路径看目录权限和属主。id 当前用户看当前用户 uid 和所在组。确认目标目录的属组是否包含当前用户。再检查父级目录的x权限路径上每一层都要有执行权限否则无法进入。最后检查 SELinux 是否阻止ls -Z 文件看安全上下文临时关闭用setenforce 0但生产环境不要图省事。这条套路能解决90%的权限问题。剩下10%往往是“文件被锁定”这种怪异情况比如chattr i给文件加了 immutable 属性这时候ls -l看不出任何异常需要lsattr file查然后用chattr -i file解开。我自己遇到过几次有人为了防止配置被误删给 nginx.conf 加了i后来改配置一直报权限不足折腾半天才想起来这个属性。还有一个高频问题就是 docker 权限错误。非 root 用户执行docker ps提示permission denied while trying to connect to the Docker daemon socket这个问题的根源是当前用户不在docker组里。处理办法sudo usermod -aG docker $USER su - $USER然后重新运行docker ps就能正常。如果还是不行检查/var/run/docker.sock权限ls -l /var/run/docker.sock正常应该是srw-rw---- root docker。如果 socket 权限不对需要调整 docker 服务启动配置或者修复 socket 文件。这个方法同样适用于 podman 或者 containerd 的类似报错。4.2 误改权限导致的系统故障修复提到权限修复我必须先警告一句永远不要执行chmod -R 777 /这类命令。即使服务器再急、再赶时间用chmod配合-R时也必须把路径写清楚。我见过有人想改/home/aaa的权限结果写成chmod -R 777 /home /aaa等于把整个/home变成了全员可写第二天数据就被误删了。如果真的把系统权限搞乱了第一步先别慌系统不会立刻崩但会越来越难用。排查优先级如下/etc/passwd、/etc/shadow、/etc/group这三个文件权限必须优先恢复。正常是644、600、644。/etc/sudoers必须是440属主 root、属组 root。/etc/ssh/*这类敏感配置文件目录权限多为700公私钥权限分别是600和644。所有系统目录/usr、/var、/boot不能随意开放写权限否则不仅影响安全还会拖垮系统更新。如果你之前没有备份权限最稳妥的恢复办法是重装核心软件包来重置文件权限。比如基于 RPM 的系统可以用rpm --setugids rpm --setperms这条命令会把系统已安装包的文件权限恢复到包出厂设置很管用。Debian 系可以用dpkg --verify检查哪些文件被改过再决定是否需要apt install --reinstall。另外日常维护时我强烈建议做一次“权限快照”备份。方法很简单getfacl -R /etc /backup/etc_permissions.acl恢复时setfacl --restore/backup/etc_permissions.acl对于整个系统中的关键目录可以定期跑一次权限备份脚本。真出事时几分钟就能把关键权限拉回来。4.3 文件权限修复与常用命令速查把平时最常用的权限修复场景整理成了表格方便直接查阅场景现象修复命令普通用户无法进入目录cd /data时报 permission deniedchmod x /data再检查属组文件属主不对ls -l显示陌生属主chown user:group file目录组写权限缺失队友无法在共享目录建文件chmod gw /data/project文件被加锁删除不了rm报 operation not permittedlsattr file后chattr -i filesocket 权限错误非 root 连不了 dockerusermod -aG docker $USER无法执行二进制./binary报没有执行权限chmod x binary内核/系统目录被改乱大量服务起不来rpm --setperms -aRPM系新建文件权限过严队友读不了新文件改 umask 或用setfacl -m u:user:rw“无权限删除”这个搜索热词在 Linux 场景下通常要看两点一是当前用户对目标文件所在目录是否有写权限二是文件是否被chattr i或 ACL 禁止删除。目录写权限解决大多数问题剩下的用lsattr排查。如果你需要精细控制某个账号对某个文件的权限可以不用改属主直接用 ACLsetfacl -m u:zhangsan:rwx /data/projectgetfacl /data/project可以查看 ACL 列表。ACL 的优先级很高它和普通权限位是叠加的而且可以灵活到“只给某一个用户写权限其他用户保持只读”。多人在服务器上协作时ACL 是比chmod更好用的工具缺点是很多工具会忽略 ACL比如某些 tar 打包命令不加--acls就会丢掉 ACL 配置。5. 长期维护账号权限的一点经验账号和权限管理不是“一锤子买卖”而是需要长期维护的工程。我在实际维护中习惯做三件事第一每季度审计一遍账号列表。用awk -F: {print $1, $3} /etc/passwd检查有没有多余账号特别是那些已经离职但还没删掉的账号用lastlog看哪些账号长期未登录确认后直接禁用。第二对 sudo 权限做最小化。把“开发人员需要重启 nginx”和“开发人员需要所有权限”分成两条配置能用一条命令解决的事绝对不开全量ALL。权限收缩时先通知使用方再在预发环境验证不要直接在线上改。第三记录变更。每次修改用户组、调整目录权限、新增 sudo 规则都简单写进 notes 或者提交到 wiki。生产环境的权限一旦乱掉排查成本极高哪怕多花一分钟记录也能给三个月后的自己省下几小时。最后分享一个我踩过多次坑后总结的体会权限问题最难的不是命令而是设计。我建议你在创建任何账号、设置任何权限之前先问自己三个问题这个账号真的需要存在吗这个用户真的需要这个目录的写权限吗这条 sudo 规则能否用更具体的命令替代想清楚再动手比事后擦屁股省心太多。
返回列表