ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Linux用户与权限管理实战:从用户组到chmod命令的完整指南

2026/9/10 10:11:22 拓冰建站 浏览量
Linux用户与权限管理实战:从用户组到chmod命令的完整指南 我到现在都记得第一次在生产服务器上闯的祸当时要把一个站点目录的属主改成运行用户手一抖敲成了chmod -R 777 /var/www然后整台机器上所有用户都能随便读写这个目录里的文件运维前辈把我叫到屏幕前训了整整一个下午。从那之后我才真正明白Linux 用户与权限管理的基础命令绝不是“记住几个参数然后敲上去”那么简单。它决定了这台机器上谁能看、谁能改、谁能执行是你有没有资格说自己“会 Linux”的分水岭。这篇文章我想把用户、组、文件权限这条主线完整讲一遍。内容包括账户体系背后的原理、日常使用频率最高的 useradd / usermod / chmod / chown 等基础命令再加上几个我踩过坑之后总结出来的实操套路和排查方法。无论你是刚入行的运维、正在准备面试的开发还是自己搭服务器玩的小白按这个顺序读下来基本就能把权限管理这块拼图凑齐了。1. 先搞懂 Linux 的用户和组再谈权限很多教程一上来就让你敲 useradd、chmod却不说清楚这些命令到底在改什么。结果就是今天记住了命令明天换台机器、换个发行版就不知道怎么用了。所以在讲命令之前我建议先把 Linux 的账户体系在脑子里建个模型。1.1 /etc/passwd 和 /etc/shadow账户数据藏在哪Linux 里所有本地用户的记录都存在两个文件里/etc/passwd和/etc/shadow。/etc/passwd是全世界都能读的以前它甚至直接保存密码哈希后来因为安全原因密码部分挪到了只有 root 能读的/etc/shadow里。/etc/passwd每行代表一个用户用冒号分成 7 个字段。举个例子root:x:0:0:root:/root:/bin/bash tom:x:1000:1000:Tom Zhang:/home/tom:/bin/bash从左到右分别是用户名、密码占位符、UID、GID、注释信息一般是姓名或描述、家目录、登录 Shell。注意那个x它不是密码只是告诉系统“真密码在 shadow 里别从这读”。/etc/shadow里存的是真正和密码认证相关的字段包括加密后的密码哈希、最近修改日期、密码有效期、警告天数、宽限天数等。普通用户看不到这个文件内容所以日常排查密码问题时基本都要 root 身份才能看。你要记住一个直觉在 Linux 里“增加一个用户”这件事本质就是往这两个文件里写一行内容同时创建对应的家目录。命令只是帮你把这些动作打包了。1.2 UID 与 GID内核眼里没有用户名用户名是人类友好的产物Linux 内核真正识别账户时用的是数字也就是 UID用户 ID和 GID组 ID。每个用户在/etc/passwd里对应一个数字 UID每个组在/etc/group里对应一个数字 GID。为什么区分这个因为权限判断的底层逻辑就是数字比较文件记录了“我是谁的UID属于哪个组GID”当进程访问文件时内核把进程的 UID、GID 和文件的属主、属组拿出来做对比进而决定放不放行。整个过程里谁的名字叫 root 还是叫 admin内核完全不关心它只认数字。所以你会发现一个现象如果你把普通用户的 UID 改成 0那它就拥有了 root 级的特权身份虽然用户名完全不同。这也是很多系统安全加固要求“不允许存在第二个 UID 0 用户”的原因。1.3 root、普通用户与 sudo 的边界root 的 UID 是 0它是 Linux 系统中的特权账户几乎不受权限限制可以读改所有文件、杀死任意进程、加载内核模块。正因为它的权限太大日常运维的基本原则是能不用 root 就不用 root能用 sudo 精准授权就尽量别直接切到 root。sudo 的作用是让普通用户临时以某一用户的身份执行命令最常见的是sudo command以 root 身份执行。它比直接切到 root 更安全还自带审计日志。你在配置 sudo 时用的是visudo编辑/etc/sudoers不要直接用普通编辑器改因为 visudo 保存时会做语法检查能避免“写错了整个系统没法再提权”的尴尬。就我的经验来看很多新人对权限没概念拿到服务器第一件事就是su root然后在生产环境里横冲直撞。真正规范的运维做法是日常操作使用普通账号需要执行管理命令时再用 sudo而且尽量精确到某几条命令别给一整个用户组发“全部放行”的权限。2. 用户管理核心命令从创建到删除一次讲完理解了账户体系之后再来看命令就会轻松很多。用户管理的命令其实围绕一个生命周期创建、修改、锁定、删除。2.1 useradd 创建用户常用参数就这几个在 CentOS、Rocky、Ubuntu、Debian 这些主流发行版里创建用户的命令都是useradd。不同发行版的默认参数差异不小这也是新手最容易踩坑的地方。比如 CentOS 系默认useradd xxx会顺手创建家目录/home/xxx但 Ubuntu 系在新版本里默认反而可能不创建家目录需要用-m参数显式创建。所以我建议你在脚本或交付标准里永远不要依赖系统默认行为而是把参数写全useradd -m -d /home/zhang -s /bin/bash -c Zhang San -u 1501 zhang逐个解释-m如果家目录不存在则创建并把/etc/skel里的骨架文件复制进去。这个是我的必加参数。-d指定家目录路径默认是/home/用户名。-s指定登录 Shell一般运维用户选/bin/bash。如果你创建的是只跑服务的系统用户可以用/usr/sbin/nologin禁止登录。-c注释信息通常是真实姓名或职责描述方便后面的人知道这个账号是给谁用的。-u指定 UID一般用于保持多台服务器之间用户 ID 一致。-g指定主组后面跟组名或 GID。如果不指定有些发行版会创建一个同名组作为主组。-G指定附加组多个组用逗号分隔。比如-G sudo,docker让这个用户有 sudo 权限、能操作 docker 组。等你创建完用户先做两件事。第一passwd zhang设置初始密码。第二检查/etc/passwd、/etc/shadow、/etc/group里的记录是否正常并确认家目录属主属组是否正确。有时候你会遇到家目录创建成功但属主是 root 的情况原因通常是useradd在创建家目录时缺少-U创建同名组或者系统 umask 配置被改过。属主不对直接会导致用户登录后连自己的.bashrc都写不了。2.2 passwd 与密码策略不只是改密码passwd是修改密码的命令但它能做的事不止这一件。普通用户运行passwd只能改自己的密码root 运行passwd 用户名可以重置任意用户的密码。注意运行之后系统会提示先输入当前密码再输入两次新密码这符合交互式安全流程。在脚本里你可以用--stdin参数实现非交互式设置密码echo Backup2025! | passwd --stdin backupsync但这样命令会被记录到 shell history 里有泄露风险我建议用 chpasswd 替代echo backupsync:Backup2025! | chpasswdpasswd的其他重要参数-l锁定用户效果是在密码哈希前加!前缀让用户无法登录。-u解锁用户移除锁定标记。-e强制用户在下次登录时修改密码。-x设置密码最长有效期-w设置警告天数例如passwd -x 90 -w 7 backupsync。我在实际工作中最常用的组合是给新员工建号时先随机生成密码再设置首次登录强制改密这样避免用明文在聊天工具里传密码。如果你用chage命令还能看到更详细的密码策略chage -l username chage -M 90 -m 7 -W 7 username # 最长90天最短7天提前7天告警很多安全基线检查里都会要求这些策略提前学会能让审计轻松很多。2.3 usermod 与 userdel改账户不是删了重建用户建错了或者需求变了很多新手会直接删掉重建。这其实不是好习惯尤其当服务器上已经有大量文件属于这个用户时删掉再建会把文件归属关系全部打乱。正确的做法是尽量用usermod去修改。常用的 usermod 参数和 useradd 基本一致只是语义变成“修改”例如usermod -l newname oldname # 修改用户名 usermod -d /data/newhome -m zhang # 修改家目录并迁移原家目录内容 usermod -aG docker zhang # 把用户加入docker组 usermod -s /sbin/nologin zhang # 修改登录Shell注意一个非常容易踩的坑-G是覆盖附加组而不是追加。如果你写usermod -G docker zhang那么 zhang 原来的附加组会被整体替换成 docker 一个组。之前加的管理组、共享组全都没了。正确做法是加-a也就是 append 追加。我见过太多人写脚本时因为漏了-a把人从一堆组里踢出去了。删除用户用userdel。如果你确定这个用户不再需要连家目录一起删userdel -r zhang我给你的建议是除非非常确定否则不要加-r。生产环境里经常有这种情况——用户离职了但资料还在家目录里你还得找回来。所以一次稳妥的删除流程是先锁定用户再等他确认不需要保留数据后再执行删除。锁定用户你可以直接用passwd -l zhang或者usermod -L zhang这样账户无法登录但数据和属主关系都还保留着后续要做需要的时候还能解锁。2.4 批量建用户的小技巧当你需要一次性创建多个用户时一条条手工敲命令效率太低。我常用的方式是一个简单的 for 循环for user in zhang li wang; do useradd -m -s /bin/bash $user echo Init2025 | passwd --stdin $user done如果要批量初始化和设置更多字段比如指定 UID、指定组可以把用户信息放进一个文本文件然后循环读。还有一个更底层的工具newusers它直接读一个格式类似/etc/passwd的文件来批量创建用户适合真正的批量场景但格式一旦写错排查起来比较麻烦我一般只在需要成百上千建账号时才用它。3. 组管理与信息查看别只会用 id用户管理离不开组。组的意义在于“批量授权”与其一个一个用户去授权不如建一个组再把用户加进组里。3.1 组管理命令 groupadd / groupdel / gpasswd创建组用groupadd最常用参数是-g指定 GID例如groupadd -g 2000 devops修改组名用groupmod -n newname oldname删除空组用groupdel。注意如果某个组是某用户的主组直接删除通常会报错需要先把这个用户的主组改掉或删掉用户才行。往组里添加、移除用户有两条途径一是前面说的usermod -aG 组名 用户名二是用gpasswdgpasswd -a zhang devops # 把zhang加入devops组 gpasswd -d zhang devops # 把zhang从devops组移除gpasswd的好处是语义清楚适合在需要频繁加减成员的场景下用。如果你管理的是大量成员需要考虑是否引入更复杂的工具比如 LDAP、FreeIPA但这超出了基础命令的范围这里不展开。3.2 查看用户和登录情况的组合拳id是最常用的命令能看到当前用户的 UID、GID 以及所属的所有组id uid1000(tom) gid1000(tom) groups1000(tom),10(wheel),1001(devops)想只看某个用户的组信息用groups zhang。想看所有用户列表直接读/etc/passwdawk -F: {print $1} /etc/passwd想排查这台机器“现在有谁在登录”“之前谁登录过”用who # 当前登录会话 w # 更详细的当前登录信息包括正在执行什么命令 last # 查看登录历史 lastlog # 查看所有账号的最后登录时间我在做服务器交接时习惯先跑一遍 lastlog能很快发现哪些账号长期没登录哪些账号从异常 IP 登录过。这也是判断是否有僵尸账号、是否存在安全隐患的快速手段。还有一个容易被忽略的命令是getent。它可以跨数据源查询账户信息比直接 grep/etc/passwd更规范getent passwd zhang getent group devops假设你的系统接入了 NIS、LDAP 等外部用户源getent就比死读本地文件可靠得多。4. 权限体系深入rwx 到底在说什么用户和组是“谁”的问题权限是“能做什么”的问题。第二部分开始进入 Linux 权限模型的核心读 r、写 w、执行 x。4.1 通过 ls -l 看懂权限位在任意目录下执行ls -l你会看到每个文件前面有一串形如drwxr-xr-x的字符。这 10 个字符的信息量很大第 1 个字符是文件类型。-普通文件d目录l符号链接c字符设备b块设备p管道s套接字。第 2-4 个字符是属主owner的权限。第 5-7 个字符是属组group的权限。第 8-10 个字符是其他人other的权限。例如-rw-r--r-- 1 root root 1234 Apr 12 10:00 config.ini这个文件的属主 root 有读、写权限但没有执行权限属组用户和其他用户都只有读权限。再看这个drwxr-xr-x 2 root root 4096 Apr 12 10:00 /var/www这是一个目录属主 root 能读能写能进入属组和其他用户能读能进入但不能在目录里创建、删除或重命名文件。4.2 rwx 对文件和目录的意义完全不同新手容易犯的错误是把权限理解成“文件能不能看、能不能改”换到目录身上就懵了。这里我给你一个特别直白的对照对普通文件来说r读能读取文件内容。w写能修改、截断文件内容。x执行能把文件作为程序运行。对目录来说r读能列出目录下的文件名也就是能执行ls。但注意如果只有 r 没有 x你能看到文件名却拿不到文件的 inode 信息ls -l反而会报错。w写能在目录里创建、删除、重命名文件。x执行能穿过目录访问其中的文件。没有 x 权限即使你知道文件路径也无法进入或读取内容。所以一个很关键的结论是要对目录里的文件做任何操作目录上至少要有 x 权限要在目录里增删文件必须同时有 w 和 x。这也是为什么很多网站主目录明明文件权限正常Nginx 却报“Permission denied”的原因之一——更上层某个目录缺了 x 权限。4.3 chmod 使用符号法和数字法chmod用来修改权限位。有两种写法我建议你都得会。符号法例如chmod ux script.sh # 给属主加执行权限 chmod g-w file.txt # 去掉属组的写权限 chmod or file.txt # 其他人的权限设为只读 chmod ax script.sh # 所有人加执行权限符号法的好处是语义直观适合微调单条权限。但如果要“全部重设”数字法更常用。数字法基于每一类用户的一组 rwx 权限来计算数值。规则是r 计 4 分w 计 2 分x 计 1 分三者相加得到一个 0-7 的数字。例如rwx 4 2 1 7rw- 4 2 6r-x 4 1 5r-- 4然后按“属主-属组-其他”的顺序写下三个数字chmod 755 script.sh # 属主rwx属组r-x其他r-x chmod 644 config.ini # 属主rw-属组r--其他r-- chmod 600 secret.key # 属主rw-属组无任何权限其他无权限权限设计我给你的默认建议是目录统一用 755 或 750普通文件用 644 或 640密钥文件和密码类文件用 600 或 400。不要轻易使用 777这也是我开篇提到的那次事故的教训。777 意味着所有用户都能读写执行等于把整个系统的安全大门敞开了。4.4 chown 与 chgrp换主人、换属组chown用来修改文件或目录的属主和属组chgrp只修改属组。格式如下chown tom:app /data/project # 属主改为tom属组改为app chown tom /data/project # 只改属主 chgrp app /data/project # 只改属组注意如果要对整个目录树递归生效加-R。但chown -R比chmod -R相对安全一些因为不会放大权限只会改归属。chown是运维高频命令尤其是部署应用、迁移网站、配置共享目录的时候。我遇到过好多次“明明给了写入权限程序还是报无权限”的案例最后查下来发现都是属主属组不对文件属主是 root但运行用户是 nginx中间所有人都被卡在权限判断之外。这里有个小习惯把“属主-属组-权限位”三件事一起确认而不要只改其中一个。我经常写完 chown 后立刻执行ls -l和namei -l /var/www/html/a/b来检查整个路径上的权限状态。4.5 umask默认权限背后的隐形控制每当你创建文件或目录时系统不会直接给你一个“随机”权限而是要经过 umask 过滤。umask 是一个掩码值它决定了默认权限能开到多大。查看当前 umaskumask通常输出是0022或0002。规则是文件的最大默认权限是 666目录是 777然后减掉 umask 值umask 022文件为 666 - 022 644目录为 777 - 022 755。umask 002文件为 666 - 002 664目录为 777 - 002 775。为什么要给普通文件扣掉执行权限这是安全考虑防止你随手创建的脚本、下载的文件意外具备执行能力。目录保留执行权限则因为它是进入目录的必需项。如果你希望团队创建的共享文件默认都有组写权限就把 umask 改成 002。修改位置根据发行版不同一般在/etc/profile、/etc/bashrc或用户自身的~/.bashrc里。注意这个改动会影响所有新建文件改之前要想清楚。5. 特殊权限与高级实操场景掌握了基础 rwx 之后我们还要聊聊三组特殊权限位SUID、SGID、Sticky Bit。它们在进阶运维和面试里都是高频考点。5.1 SUID / SGID / Sticky Bit 三种特殊权限SUIDSet UID作用于可执行文件。它让任何用户执行该文件时进程的隶属 UID 都自动切换为文件属主的 UID而不是执行者的。最典型的例子是/usr/bin/passwdls -l /usr/bin/passwd -rwsr-xr-x 1 root root 62336 ...普通用户想改自己的密码就必须写入只有 root 能写的/etc/shadow。如果 passwd 没有 SUID 位普通用户根本没法改密码所以系统默认给它加了 SUID。SUID 用符号法表示为s数字法是 4000设置方式chmod us /path/to/file chmod 4755 /path/to/fileSGIDSet GID作用于可执行文件时效果类似 SUID但继承的是组身份。真正在运维中用得更多的场景是作用于目录目录开启 SGID 后任何在该目录下新建的文件或目录属组都会自动继承这个目录的属组而不是创建者自己的默认组。chmod gs /data/share chmod 2770 /data/shareSticky Bit粘滞位主要作用于公共目录比如/tmp。它的效果是在带粘滞位的目录里只有文件属主、目录属主或 root 才能删除或重命名文件其他用户即使对目录有写权限也无法乱删别人的文件。ls -ld /tmp drwxrwxrwt 20 root root ...看到最后的t了吗这就是粘滞位。设置的命令chmod t /data/shared chmod 1777 /data/shared需要提醒的是SUID 是个双刃剑。一个拥有 root 权限的可执行文件只要存在就可能成为提权攻击的跳板。你在生产环境里新增 SUID 文件要谨慎平常也可以定期扫描系统中所有带 SUID/SGID 位的文件排查异常find / -perm -4000 -type f 2/dev/null find / -perm -2000 -type f 2/dev/null5.2 实操场景一给新同事开一个运维账号假设团队来了个新同事小张他需要做常规运维但不想给他完整 root 权限。我会这样操作# 1. 创建用户 useradd -m -d /home/zhang -s /bin/bash -c Zhang San zhang # 2. 设置临时密码并强制首次登录改密 echo Temp2025 | chpasswd chage -d 0 zhang # 3. 加入 wheel/sudo 组注意这里用 -aG 追加 usermod -aG wheel zhang # 4. 备份机制把家目录初始骨架文件检查一下 ls -la /home/zhang/如果你想精确控制他能执行哪些命令就在/etc/sudoers.d/下放一个独立文件zhang ALL(ALL) /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx这样小张只能用 sudo 执行 systemctl 的 restart 和 status 命令其他命令一律拒绝。配置完用visudo -c检查语法。5.3 实操场景二网站目录的权限规划一个典型 LNMP 环境Nginx 运行用户是 nginxPHP-FPM 运行用户可能是 php-fpm 或 www。代码部署用户是 deploy。合理的权限分层是代码文件属主deploy属组www目录权限 750文件权限 640。上传目录比如uploads/属主 www属组 www目录权限 750 或 770保证 PHP 进程能写入。静态缓存目录属主 nginx属组 www目录权限 750。配置文件和敏感文件属主 root属组 root权限 640 或 600。命令上类似这样chown -R deploy:www /var/www/example.com chmod 750 /var/www/example.com find /var/www/example.com -type f -exec chmod 640 {} \; find /var/www/example.com -type d -exec chmod 750 {} \; chown -R www:www /var/www/example.com/uploads chmod 750 /var/www/example.com/uploads核心原则是最小权限让 nginx 能读让 PHP 能读写需要写的目录让部署用户能改代码其他人一概不给。不要图省事直接chmod -R 777不然一旦 Web 服务被攻破攻击者拿到的是整个文件系统的改写权限。5.4 实操场景三部门共享文件的协作目录团队协作时最常见的需求是“我们部门的人都能在这个目录下增删改文件但不能乱删别人的文件”。这个场景可以综合用上 SGID 和 Sticky Bit。# 1. 创建共享组和目录 groupadd finance mkdir -p /data/finance # 2. 修改属组并设置权限 chown root:finance /data/finance chmod 2770 /data/finance # 3. 开启粘滞位防止用户相互删除文件 chmod t /data/finance # 4. 将财务部成员加入 finance 组 gpasswd -a alice finance gpasswd -a bob finance这样/data/finance的效果是finance 组成员能读写进入但每个用户在目录里创建的文件只能由本人或 root 删除。SGID 又保证新子目录会自动继承 finance 组不需要反复 chgrp。这是一套很实用的企业内部分区方案。6. 常见问题排查与避坑实录最后这部分我整理几个平时最常遇到的现象和排查思路。看起来是小事但真踩过坑的人都知道它们足以让一台服务从正常变成不可用。6.1 问题一Permission denied到底是谁拒绝了你遇到Permission denied时很多人第一反应是给文件加 777这是很危险的做法。正确的排查顺序先看错误信息里提到的是哪个路径然后逐个分析路径上每个目录的可进入权限ls -l /var/www/html/index.php namei -l /var/www/html/index.phpnamei -l会列出路径上每一级目录和文件的权限、属主、属组能快速定位是哪一层缺少 x 权限。接下来确认运行进程的用户是谁ps -ef | grep nginx例如 Nginx worker 以 nginx 用户运行若/var/www/html的属组是 www权限是 750nginx 用户不在 www 组里那就无法访问。解决办法要么把 nginx 用户加入 www 组要么调整目录其他用户权限为 5要么修改属组。具体怎么选要看你的安全策略而不是无脑加权限。6.2 问题二sudo 用不了提示用户不在 sudoers有两种常见情况。一是用户确实没被加入 sudo 组二是用户的组身份是新增的但当前登录会话里还没生效。第二种尤其容易迷惑人你明明刚把用户加进了 sudo 组用户却告诉你还是不能 sudo。原因很简单用户登录时的组信息是在登录那一刻抓取的已经打开的 SSH 会话不会自动刷新。解决办法是让用户退出重登或者执行newgrp sudo或者干脆用 root 重新分配一个会话。还有一种情况是 sudoers 文件写坏了。如果不小心把文件改错会提示 “sudo: no valid sudoers sources”。这时要切换到 root 或者能写入的终端用pkexec visudo之类的命令修正。更稳妥的做法是用 root 账号检查/etc/sudoers语法保证格式正确。6.3 问题三用户删了文件却“活”着服务器上经常出现这种情况用户离职管理员执行userdel -r删除了账号但没多久发现磁盘空间还是被大量文件占着那些文件显示的数字 UID 很奇怪比如1001而不是用户名。这是因为那些文件在删除用户之前就已经存在而userdel -r只删除家目录下的文件不负责清理其他地方由这个用户创建的文件。你可以用下面命令找到所有“无主文件”find / -nouser -o -nogroup 2/dev/null处理方式有两种。如果是误删需要重建相同 UID 的用户来接管如果确认不要了可以把这些文件统一归到一个“归档用户”名下或者直接清理。有时候被删用户的进程还在跑文件还会继续产生那就先把进程处理掉再收尾。6.4 避坑清单给新手的最后提醒不要在生产环境随手执行chmod -R 777 /、chown -R 某个用户 /这类危险命令尽量把 -R 限定到具体的项目目录。修改/etc/passwd、/etc/shadow、/etc/sudoers之前先备份一份确认语法正确再覆盖。给用户加附加组时记得用usermod -aG不要漏了-a。删除用户前先锁定、先确认文件归属给后续留条退路。模板化创建用户时别依赖发行版的默认参数把-m -d -s都写清楚避免不同系统行为不一致。排查权限问题时先把“属主、属组、权限、运行用户、路径上级目录”这五个要素列出来按顺序检查比乱试 chmod 高效得多。我在实际运维中还有一个习惯只要动过权限配置就会把改动记录到变更文档里哪怕只是改了一个目录的属组。权限问题是最难肉眼排查的问题之一等两周后有人问你“这个目录为什么变成这样”你能拿出当时的记录会省掉无数互相猜疑的时间。最后再分享一个小技巧如果你发现自己反复在调试同一套目录权限说明大概率已经把权限结构弄得过于复杂了。停下来重新按“运行用户、数据用户、管理用户”三层模型梳理一遍。Linux 的权限模型其实很朴素复杂的是人把权限用复杂了。能把一套权限保持简单、可解释、可回溯比背下任何一条命令都值钱。