Linux系统用户管理和文件目录权限,这两块内容你翻任何一本Linux教程都能看到,但真正到了生产环境下,能把用户建明白、权限给得恰到好处、目录文件不乱成一锅粥的人,说实话不多。我这些年折腾Linux,从虚拟机上瞎捣鼓到给几十台服务器做日常运维,踩过的坑绝大部分都集中在用户、组、文件权限这三者的交叉地带。这篇文章就是把我在实际工作里反复用到的那套东西整理出来,不堆概念,全是能直接上手敲的命令和思路,适合刚接触Linux的初学者,也适合那些已经开始维护服务器、但总在权限上栽跟头的朋友。
1. 用户管理的核心逻辑与常用命令
1.1 为什么Linux要区分用户
很多新手有个误区,觉得Linux的用户系统就是用来加账号、删账号的,其实没那么简单。Linux是一个多用户多任务操作系统,它的用户体系本质上是一套访问控制边界。系统里跑的每个进程、每份文件、每个定时任务,背后都有一个身份归属,这个身份就是用户和用户组。把用户建好、把目录权限配好,等于给你的服务器画好了房间隔断,哪个服务能进哪个房间、谁能动哪个柜子,一清二楚。
Home目录这个概念也贯穿始终。每当创建一个普通用户时,系统通常会在 /home 下生成一个同名目录,这个目录是用户的私有空间,里面存放配置文件、代码、数据,默认权限是700,也就是除了用户自己,其他人一律不可进入。这个设计从根上保证了多用户环境下各人数据的隔离,不会出现你写的代码被旁边同事随手改掉的情况。
还有一点非常重要:Linux里的用户分为系统用户和管理员用户。管理员root的UID是0,拥有对所有文件的所有权限。其他系统服务如sshd、nginx、mysql,一般都有自己的专用系统用户,这些用户通常是nologin的,设计目的就是让对应服务的进程持有一个独立的权限身份,避免所有进程都用root跑,防止一个服务被攻破后整个服务器沦陷。
1.2 创建用户:useradd的完整用法
创建用户最常用的命令是useradd,但它的默认行为在不同发行版上差别很大。CentOS和Ubuntu就不同:Ubuntu上useradd默认不创建home目录,CentOS的useradd则默认创建。我自己为了统一习惯,无论在哪台机器上都会显式带上参数,绝不依赖默认行为。
一条完整的新用户创建命令我通常是这样的:
bash复制useradd -m -d /home/zhangsan -s /bin/bash -c "Zhang San" -u 1001 -g dev -G docker zhangsan
逐个拆解一下参数的含义:
-m:创建用户的同时创建home目录。-d:指定home目录的路径,如果不指定就默认在 /home/用户名。-s:指定登录shell,生产环境如果用户不需要登录,就填 /sbin/nologin 或 /usr/sbin/nologin,这是很多服务账号的标准配置。-c:用户的备注信息,一般写真实姓名或用途,方便日后管理。-u:手动指定UID,多台服务器之间想保持同一用户UID一致时非常有用。-g:指定主组,组必须已存在。-G:指定附加组,可以跟多个组,逗号隔开。
创建完之后,需要设置初始密码:
bash复制passwd zhangsan
系统会让你输入两次,输入的时候屏幕上没有任何回显,这是正常现象,不是键盘坏了。
如果用户只用来跑服务、不允许登录,用这种方式创建:
bash复制useradd -M -d /var/lib/nginx -s /usr/sbin/nologin nginx
-M 是不创建home目录,-s 指定nologin。运行nginx的进程就用这个身份,权限被锁定在nginx工作目录里,出问题也没有提权路径。
1.3 用户信息都存到了哪里
搞清楚用户信息存放位置,排查问题时可以少走很多弯路。用户的所有信息主要存在四个文件里:
| 文件 | 字段 | 作用 |
|---|---|---|
| /etc/passwd | 用户名:x:UID:GID:备注:home目录:登录shell | 用户信息主表,任何用户可读 |
| /etc/shadow | 用户名:密码哈希:最近修改时间:最小修改间隔:最大有效期:警告天数:宽限天数:过期日期:保留字段 | 密码及密码策略,仅root可读 |
| /etc/group | 组名:x:GID:组成员列表 | 用户组信息 |
| /etc/gshadow | 组名:加密的组密码:组管理员:组成员 | 组密码信息,极少使用 |
/etc/passwd 每一行都是冒号分隔的七段内容,关键是第二段如果是个x,说明真正的密码在 /etc/shadow 里,这是现代Linux的标准做法,防止密码哈希被普通用户拖走暴力破解。
我特别提醒一点:尽量不要手动编辑这两个文件来添加用户,一个冒号写错位、一个字段漏了,就可能导致用户无法登录甚至系统启动异常。要用命令去改:useradd、usermod、passwd。如果真碰到必须手改的情况,建议先备份原文件:
bash复制cp /etc/passwd /etc/passwd.bak
cp /etc/shadow /etc/shadow.bak
修改完后还可以用 pwck 命令校验一下文件的完整性,它会检查字段数量和格式是否合法。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 从用户到权限:文件目录权限模型
2.1 权限三位一体的含义:rwx
Linux的文件权限模型,可以用一句话概括:对文件或目录的访问权限,取决于你是属于哪个身份的用户。每个目录或文件有九位权限位,分成三组,依次是属主(u)、属组(g)、其他用户(o),每组三位,分别是读(r=4)、写(w=2)、执行(x=1)。
很多人背了数字法却不知道在场景里怎么用,这里我说点直白的理解。对一个普通文件来说:
- r:可以查看文件内容,比如cat。
- w:可以修改文件内容,注意这需要目录也放开写权限,否则你连在目录里新建同名文件替换都做不到。
- x:可以作为程序执行。
对一个目录来说,语义就变了:
- r:可以列出目录里有哪些文件名。
- w:可以在目录里创建、删除、重命名文件。
- x:可以进入目录内部,并且访问其中文件的具体属性。
这里有个大部头新手容易忽视的点:目录的w权限决定了能否删除里面的文件,和文件本身的权限没有直接关系。换句话说,就算一个文件是只读的,只要它所在目录对用户开放了写权限,这个用户可以把文件删了重建一个内容完全不同的同名文件。所以生产环境中,共享目录一般避免直接给予部分用户目录的w权限,而是通过ACL来做更细的授权,后面会专门讲。
2.2 chmod、chown、chgrp的实用写法
修改权限基本就三件套:chmod改权限位,chown改属主和属组,chgrp单独改属组(其实chown也能干这事,用哪个看习惯)。
我最常用的数字写法是:
bash复制chmod 755 /data/www
chmod 644 /data/www/readme.txt
那么 755 是怎么算出来的?7 = 4+2+1,属主可读写执行;5 = 4+1,属组和其他用户可读可执行不可写。644 则是属主可读写,其他人只读。
符号写法也很常用,好处是直接明确,比如只给属主增加执行权限:
bash复制chmod u+x /data/run.sh
chmod g-w /data/www
chmod o-r /data/secret
这个写法是谁加谁减符号直接拼出来,配合文件名,一眼就能看懂干了什么,适合在交接的运维文档里留记录。
改属主属组时注意顺序,冒号前的属主,冒号后是属组:
bash复制chown zhangsan:dev /data/www
chown -R zhangsan:dev /data/www
-R 是递归,会把目录下所有子目录和文件一起改掉。这里提醒一句:递归修改生产目录前,一定要先检查目录里有没有链接,因为chown会跟随符号链接,可能把链接指向的远端文件属主也改了,严重情况下会导致其他应用起不来。
2.3 特殊权限位:SUID、SGID与粘滞位
常用权限之外,还有三个特殊权限位,很多系统故障就是栽在这上面,尤其是SUID。
SUID设置在执行文件上时,进程运行期间会临时获得文件属主的身份。典型代表是 /usr/bin/passwd,它的权限是 -rwsr-xr-x,注意属主权限位上的s。普通用户执行passwd修改自己的密码时,需要写 /etc/shadow,而这个文件普通用户根本没权限,正是因为passwd程序带有SUID,进程临时提升为root身份,才能完成写入操作。
查看系统中所有带SUID/SGID位的文件,用下面的命令:
bash复制find / -perm /6000 -type f 2>/dev/null
如果发现某个非系统自带的二进制文件有SUID权限,尤其是属主是root的,基本可以断定有问题,这类权限一旦配合程序漏洞,很容易被用来提权。
粘滞位则常见于 /tmp 目录,权限是 drwxrwxrwt。它的作用是:目录允许所有用户写入,但只有文件属主才能删除自己的文件。这就避免了多人共用的临时目录里,A用户建的敏感临时文件被B用户随意删掉。
给目录设置粘滞位:
bash复制chmod +t /tmp
它还有一个很实用的场景:多人协作的共享项目目录,如果大家都要往里面传文件,又希望每个人只能删自己的内容,那就给目录加上粘滞位。
3. 高频实操场景:项目部署与共享目录权限分配
3.1 初始化部署用户与项目目录的完整流程
我以部署一个名叫 demo 的Web项目为例,完整走一遍从账号到目录权限的初始化流程。这个项目由三名开发人员负责,分别是 zhangsan、lisi、wangwu,他们需要共享 /data/demo 目录,往里面提交代码构建产物和日志文件,但都不允许登录服务器做其他操作。
第一步,创建专用部署用户,不给登录shell:
bash复制useradd -M -d /data/demo -s /sbin/nologin demo
useradd -M -s /sbin/nologin zhangsan
useradd -M -s /sbin/nologin lisi
useradd -M -s /sbin/nologin wangwu
第二步,创建项目目录并设置属主属组:
bash复制mkdir -p /data/demo/logs /data/demo/www
chown -R demo:demo /data/demo
chmod 750 /data/demo
第三步,把开发人员加入demo组,并让他们对项目目录可读可进入:
bash复制gpasswd -a zhangsan demo
gpasswd -a lisi demo
gpasswd -a wangwu demo
chmod 750 /data/demo
现在目录权限是750,属主是demo,属组是demo组,组内用户有读和进入的权限,没有写权限。业务进程可以写,其他用户只能看,权限边界很清晰。
如果有人需要写日志目录,单独给logs目录开组写权限:
bash复制chmod 770 /data/demo/logs
项目目录和日志目录权限需求不一样,分开设置就对了,不要图省事直接对整个项目目录开777,那等于把门打开让任何人进来,日志被人篡改了都不知道。
3.2 精细授权:ACL解决跨组共享的痛点
权限位只有三组,分类太粗,真实业务经常碰到这种场景:项目组一群人在demo组里,现在来了一个协作者,只需要查看特定目录的内容,不需要写,也不需要进其他目录。这时用传统权限位改来改去,很容易把原有权限改乱。
用ACL(Access Control List)可以解决:ACL允许你对任意一个用户或组单独设置对路径的权限。
给他单独加读和进入的权限:
bash复制setfacl -m u:zhaoliu:r-x /data/demo/www
查看ACL:
bash复制getfacl /data/demo/www
输出会看到多了这样一行:
code复制user:zhaoliu:r-x
如果想让新增的文件默认继承这些ACL规则,给目录加默认ACL:
bash复制setfacl -m d:u:zhaoliu:r-x /data/demo/www
这样一来,之后在www目录里新建的文件都会自动带上zhaoliu的读执行权限,不用再挨个去改。
移除ACL也很直接:
bash复制setfacl -b /data/demo/www
-b 移除所有ACL。生产环境里ACL用得好能省很多事,但也要注意两点:第一,ACL会体现在ls -l的输出末尾,出现一个+号;第二,配合rsync备份时最好加 -A 参数保留ACL,否则备份过去的文件权限会丢失,恢复的时候又得重配一遍。
3.3 权限之外的常规强化:sudo提权与密码策略
实际工作里不可能让开发或运维每次都切到root去执行命令,sudo是更安全和可审计的方案。sudo的配置通常维护在 /etc/sudoers 里,这个文件必须用 visudo 命令编辑,不要直接用vim改。因为visudo在退出时会做语法检查,语法错了会拒绝保存,不会让你把系统sudo搞坏。
给一个用户完全的管理员权限,在文件里加一行:
bash复制zhangsan ALL=(ALL) ALL
只允许运行特定命令,比如重启nginx、检查服务状态:
bash复制zhangsan ALL=(root) /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx
这里面有个细节:sudo配置里允许的命令必须写绝对路径。拿到一个软件路径可以用 which nginx 或者 command -v nginx 查,写错路径会导致sudo执行报command not found。
密码安全策略方面,新人的常见做法是设置一个密码就完事了,但密码是有周期的。用chage可以查看或修改密码策略:
bash复制chage -l zhangsan
chage -M 90 -m 7 -W 14 zhangsan
-M 90表示密码最长有效90天,-m 7表示修改密码后至少7天内不能再次修改,-W 14是密码过期前14天开始提醒用户。对一个内部系统来说,这些参数防止有人在同一个密码上无限期用下去,同时对运维自己也是提醒:你手上的账号不会因为忘了换密码而失效。
另一个常用操作是紧急锁定用户:
bash复制usermod -L zhangsan
这个会锁定用户,密码无法再匹配,所有通过密码认证的登录都会被拒绝。等查明情况后再解锁:
bash复制usermod -U zhangsan
4. 常见问题排查与避坑经验
4.1 用户创建与删除的隐性坑位
删除用户的事故不少,特别是刚学Linux的那段时间。userdel的常用参数是-r,意思是连同home目录和mail spool一起删掉。不同发行版上userdel的默认行为也不一致,有的发行版不带-r时只删账号不删文件,导致一个残留的home目录和一个新创建的同名目录权限纠缠不清。
我自己删用户时一定会先做一次全盘扫描:
bash复制find / -user zhangsan -ls 2>/dev/null
看看这个用户到底在系统里留了多少文件。确认无需要保留的内容后再执行:
bash复制userdel -r zhangsan
如果scan后发现文件还在其他目录里,除非确认不需要,否则别急着删账号,先把有用文件用chown -R root:root 转移归属,再删用户,这样日后排查不会因为找不到属主而抓瞎。
还有一个常见坑:shell被设成 /sbin/nologin 的用户,如果你用su想切到它,会得到一个“This account is currently not available.”的提示,看起来像账号坏了,其实不是,就是这个shell拒绝登录。如果确实需要这个账号登录操作,用usermod -s /bin/bash 改回去即可。
4.2 目录权限与umask导致的集体故障
有一次我自己搭测试环境,写了个脚本定时往 /data/backup 目录生成备份文件,第二天发现另外的同事可以通过rsync读取到备份,但他完全不应该有这个权限。排查了半天,发现是脚本运行时的umask值是0022,新建的文件默认权限是644,目录是755,等于全系统所有人可读。
这个问题本质上是新建文件时机器的权限掩码控制的。umask的意思不是允许哪些权限,而是屏蔽掉哪些权限。常见的umask值:
| umask | 文件默认权限 | 目录默认权限 | 适用场景 |
|---|---|---|---|
| 002 | 664 | 775 | 多用户协作同组读写 |
| 022 | 644 | 755 | 常规默认,最低限度公开 |
| 077 | 600 | 700 | 高安全,仅属主可访问 |
每个用户可以在自己的 ~/.bashrc 末尾改umask值:
bash复制echo "umask 002" >> ~/.bashrc
但全局生效则要改 /etc/profile 或 /etc/bashrc,强烈建议改之前确认影响范围,否则整个系统的文件权限默认值都会变。
4.3 日常运维命令速查表
最后整理一份我贴在电脑屏幕边上的用户和文件目录速查表,排查问题时照着敲就行。
| 需求 | 命令 |
|---|---|
| 查看当前用户 | whoami / id |
| 查看用户所属组 | groups zhangsan |
| 列出所有用户 | cut -d: -f1 /etc/passwd |
| 列出所有组 | cut -d: -f1 /etc/group |
| 创建用户并建home目录 | useradd -m -s /bin/bash zhangsan |
| 修改用户home目录 | usermod -d /data/zhangsan zhangsan |
| 锁定用户 | usermod -L zhangsan |
| 解锁用户 | usermod -U zhangsan |
| 创建组 | groupadd dev |
| 删除组 | groupdel dev |
| 把用户加到附加组 | gpasswd -a zhangsan dev |
| 把用户从组移除 | gpasswd -d zhangsan dev |
| 设置目录属主属组 | chown -R zhangsan:dev /data/demo |
| 查看文件的权限和属主 | ls -l 文件 |
| 查看目录的权限和属主 | ls -ld 目录 |
| 查看真实权限含ACL | getfacl /data/demo |
这些命令不用死记,但一定要知道在什么时候该查哪一条。我个人的习惯是,拿到一台不熟悉的Linux机器,第一件事就是 id,看看当前用户是谁、属于哪些组;第二件事是 ls -ldn /data /tmp /var,看这些核心目录的属主和权限是否正常。-n参数可以直接显示UID和GID的数字,避免用户名映射不同带来的误导,这个细节在处理NFS共享环境时尤其重要。
聊到这,我突然想起前阵子帮人查的一套Nagios监控脚本,所有插件都是root写的,跑起来用的是服务账号,结果一堆脚本因为读不了 .netrc 文件永远返回权限错误,闹了半个月没找到原因。其实问题就出在脚本作者没仔细想进程运行身份和文件属主的关系。用户管理和文件权限从来不是一组孤立的命令,它决定了你的服务以什么身份在跑、它能碰哪些文件、别人能碰它哪些文件。把这条主线打通,很多Linux运维问题你自己就能推到八九不离十。你先拿一台虚拟机把今天这几个场景试一遍,从建用户到改权限再到设置ACL,走完一轮理解会更深。
