刚接触Linux的朋友几乎都会问同一个问题:为什么Linux非要搞出这么多用户,我直接一个root用到底不行吗?我最早学Linux时也是这么想的,后来在服务器上栽了几次跟头才明白,用户体系不是在为难你,而是在给系统分层设防。这篇我从实战运维的角度,把Linux用户管理和系统基础操作完整串一遍,包括怎么建新用户、怎么用wheel组分配sudo权限、怎么限制SSH登录、怎么看用户状态、怎么查资源限制,以及最常见的“权限被拒”问题排查思路。适合刚从Windows切过来、正在学Linux运维、或者已经被各种Permission denied折腾到头疼的读者。
1. 使用Linux前,先把用户和权限这套逻辑理清楚
1.1 为什么Linux坚持“多用户”而不是“单管理员”
很多人第一次登上Linux服务器,第一反应是:这不就是个操作系统吗,搞那么多账号干嘛?其实Linux天生继承Unix的基因,从设计第一天起就是多用户多任务系统,核心思路是“一个系统,多个身份,互相隔离”。想象一下小区门禁和一把万能钥匙的区别:如果所有住户共用一把万能钥匙,一旦钥匙丢了或者某个住户心怀不轨,整栋楼都完蛋;但如果每个住户只有自己那层的门禁卡,出事了能查到是谁在什么时间刷的卡。
这套逻辑落到Linux上就是这个效果:root是那个万能钥匙,普通用户是各自的门禁卡。日常操作只用普通用户,需要管理员能力时再用sudo临时提升权限,这样即使某个账号被攻破,攻击者也只拿到普通用户权限,系统核心目录动不了。反过来,如果你天天用root跑业务、配环境、下载文件,一旦手滑执行了恶意脚本,整个系统就裸奔了。我的建议很明确:root只用于系统级排障和安装基础组件,其它一切操作都走普通用户加sudo。
1.2 三个文件看懂用户体系:/etc/passwd、/etc/shadow、/etc/group
Linux的用户体系其实不神秘,所有用户信息就落在几个文本文件里。很多人觉得难,是因为没拆开看过。先看字段最直观的/etc/passwd,每一行代表一个用户,用冒号分成7段:
bash复制[root@localhost ~]# head -3 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
从左到右依次是:用户名、密码占位符(真正的密码不在这里)、UID、GID、用户描述、家目录、登录Shell。其中Shell写/sbin/nologin的用户,意味着不能交互式登录,这类一般是系统服务的运行账号,不需要人登进去操作。UID也很关键:0是root,1到999通常是系统用户,1000以上才是可登录的普通用户。
/etc/shadow才是存密码哈希的地方,普通用户读不了,只有root能看,字段里包含加密后的密码串、最近修改密码时间、密码有效天数、过期警告天数等。最后一个/etc/group保存用户组信息,类似passwd的结构,组名、GID、组成员都在里面。实际查看时不用记文件路径,直接打id和getent很快:
bash复制id dev01
getent passwd dev01
getent group dev01
这里有个经验:虽然这三个文件是文本,但你千万别用vim手动改,格式一旦写错可能导致用户无法登录甚至系统起不来。要改用户、加用户,一律useradd、usermod、passwd这些标准命令去操作。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 新建用户的完整实操:从useradd到首次登录
2.1 useradd和adduser到底该用哪个
新手最容易懵的点就在这:有的教程让你用useradd,有的让你用adduser,两个名字看起来都像“加用户”。实际区别要看发行版。在CentOS、RHEL、Rocky这类RedHat系系统里,adduser就是useradd的软链接,两个命令完全一样;在Debian、Ubuntu里,adduser是一个更人性化的交互脚本,它会一步一个提示地让你设置密码、填姓名,useradd则是最底层的原始命令。
所以我的用法是:在Ubuntu上临时添加一两个交互式用户,直接用adduser省事;批量建用户、写脚本、或者想精细控制每个参数时,用useradd更稳。记住一个原则:工具可以不同,但最终落到底层都是useradd那套参数体系,学会useradd就走遍天下了。
2.2 带参数创建用户:常用选项逐个拆解
useradd不带参数也可以建用户,但这样出来的用户没有家目录,登录Shell也是默认的sh,用起来很别扭。生产环境里我推荐把参数写全,习惯成自然:
bash复制sudo useradd -m -s /bin/bash -G wheel -c "dev user" dev01
逐个拆开看:
- -m:创建用户的同时创建家目录,生成/home/dev01。不加这参数,用户登进去连自己的工作目录都没有,很多程序会报错。
- -s /bin/bash:指定登录Shell,对运维人员来说通常是/bin/bash,功能全、历史记录、补全都好用。如果建的是纯服务账号,推荐写成/sbin/nologin,禁止登录,降低风险。
- -G wheel:把用户加入附加组wheel。wheel组在多数发行版里默认就是管理员组,加入后才有sudo资格,后面专门讲。
- -c "dev user":给用户加一段注释,一般是姓名或用途说明,方便以后看passwd文件知道这个账号是干嘛的。
如果想自定义UID或GID,加-u和-g参数:
bash复制sudo useradd -m -u 1500 -g 1000 -s /bin/bash app01
系统用户则用-r,比如创建一个运行服务用的账号:
bash复制sudo useradd -r -s /sbin/nologin -d /var/lib/myapp myapp
建完之后用id命令验证,顺便看一下家目录和Shell是否如预期:
bash复制id dev01
ls -ld /home/dev01
2.3 设置密码与“首次登录必须改密”的强制策略
用户建好了不代表能登录,因为passwd文件里那个x只是占位符,真正密码还空着。设置密码的命令很直接:
bash复制sudo passwd dev01
系统会提示你输两次新密码,输的时候不显示字符是正常的,别以为键盘坏了。这里有个坑:如果你用root给普通用户设密码,系统会认为你是在“管理员帮用户重置密码”,不会强制校验复杂度,哪怕你设个123456也能过;但普通用户自己改自己密码时,复杂度校验会很严格。所以安全策略必须靠自觉,我一般会顺手把密码策略设置好,至少要求定期更换。
强制用户首次登录就改密码是正规操作的标配,一行命令搞定:
bash复制sudo chage -d 0 dev01
这个命令的意思是“把最近一次修改密码的日期置为过去”(0代表1970年),用户下次一登录就会被要求立即改密码。有些人在批量初始化账号时懒得跑这一步,密码就一直是初始值,安全隐患非常大。建议任何批量建号流程里,都把chage -d 0作为固定动作。
2.4 删除用户的正确姿势与常见坑
删除用户比创建用户更要注意遗留问题。最基本的删除是:
bash复制sudo userdel dev01
但这样删完,/home/dev01目录还在,用户之前拥有的文件也还在,只是文件属主从用户名变成了一串数字UID。想连家目录和邮件目录一起清理,用:
bash复制sudo userdel -r dev01
-r这个参数会删除用户的家目录和/var/mail下的用户邮箱文件。不过即使加了-r,用户曾经在其它路径下创建的文件也可能会变成无主文件,这些文件以后清理起来很麻烦。所以我的建议是删除用户前先盘点一下他名下的文件,用find找出所有属主为某个用户的文件:
bash复制sudo find / -user dev01 -ls 2>/dev/null
看过之后再决定哪些需要备份、哪些随他一起删。另外,如果用户当前还登录着系统,userdel会直接报错提示“user dev01 is currently used in process”,这时应该先kill掉他的进程,再执行删除。
3. 别让root裸奔:wheel组和sudo的权限边界
3.1 root特权的两种路线:su和sudo
Linux给普通用户临时获取管理员权限的路径主要有两条:su和sudo。su是切换用户,比如su - 会让你输root的密码,然后整个会话变成root身份;sudo则是在当前用户身份下,以root权限执行某一条命令。
我强烈推荐用sudo而不是su。原因有三点:第一,su要暴露root密码,知道root密码的人越多,系统越不安全;而sudo只需要用户自己密码,root密码可以始终保密。第二,su切换之后所有命令都以root身份运行,万一跑错了都不知道是哪条命令造成的;sudo则可以在/var/log/secure或auth.log里记录下“哪个用户、什么时间、执行了什么命令”,出了问题能追溯。第三,sudo可以细粒度控制,只允许某个用户执行特定命令,比如只让他重启nginx,而不是给他全部管理权限。
所以正规的服务器管理策略应该是:root密码躺在保险柜里,平时谁也不许用;运维人员都用个人账号加sudo,谁干了什么都在日志里留着。
| 维度 | su | sudo |
|---|---|---|
| 所需密码 | root密码 | 当前用户密码 |
| 权限范围 | 整个shell都是root | 仅单条命令提权 |
| 审计能力 | 基本没有 | 有日志可查 |
| 风险等级 | 高,易误操作 | 低,可控性强 |
3.2 配置wheel组:哪些人能执行sudo
wheel组是传统Unix里的管理员组,在主流Linux发行版里,把用户加进wheel就等于给了他sudo资格。但你可能会发现,自己明明把用户加入了wheel组,执行sudo却还是提示不在sudoers文件中。这是因为,发行版/etc/sudoers里默认那行%wheel ALL=(ALL) ALL可能是被注释掉的,需要手动放开。
修改sudoers文件一定要用visudo命令,而不是vim直接改。visudo会做语法检查,如果配置写错了,保存时系统会拦你一手,避免把sudo搞坏导致所有人都无法提权。在RedHat系里,放开这行配置:
bash复制sudo visudo
找到这一行并取消注释:
bash复制%wheel ALL=(ALL) ALL
这行的含义拆开看:%wheel表示匹配wheel组;第一个ALL表示适用的主机;(ALL)表示可以切换成任意用户身份;最后的ALL表示可以执行所有命令。如果想让wheel组成员执行sudo时不用反复输密码,可以加NOPASSWD项,但不建议给全部命令NOPASSWD,安全隐患太大。我只会在特定的脚本调用场景下,给某几个特定命令配置免密:
bash复制%wheel ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx
3.3 实战:设置只有wheel组用户可以SSH登录
很多被爆破过的服务器,问题都出在两点:root能直接SSH登录、普通用户太多。把SSH登录限制到只有wheel组成员才能进,是性价比极高的一道防线。
修改/etc/ssh/sshd_config,重点配置两块。第一,明确拒绝root直接登录:
bash复制PermitRootLogin no
第二,用AllowGroups或AllowUsers限制可登录的用户集合,两个都用也行:
bash复制AllowGroups wheel
配置改完不要直接重启sshd,先检查语法再平滑重载:
bash复制sudo sshd -t
sudo systemctl reload sshd
sshd -t是测试配置对不对,这一步不能省,写错可能导致SSH服务起不来。重载成功后,普通用户SSH登录时会被直接拒绝,提示“Disconnected from authenticating user ...”。这是我最常用的服务器加固手段之一。
这里有个很关键的提醒:如果你正在通过SSH操作阿里云、腾讯云或公司机房远程服务器,千万千万先另开一个终端窗口测试登录成功后再关当前连接,别把自己唯一的窗口锁死。我见过不止一个同事,改完sshd_config还没测试就重载了,结果session断了又登不进去,最后只能通过机房带外管理或者云控制台VNC去救。
如果想临时改回允许root SSH登录,把PermitRootLogin改回yes,或者把AllowGroups那一行注释掉再reload即可。但有了前面这层限制,临时开放权限时也要尽量缩小来源IP,配合防火墙一起做,别裸奔太久。
4. 用户状态与登录痕迹:锁定、过期、追溯
4.1 锁定与解锁用户账户
新用户入职开账号,离职锁账户,这是用户管理的基本日常。锁定账户最常用的命令是passwd的-L参数,或者usermod的-L参数,效果差不多:
bash复制sudo usermod -L dev01
sudo passwd -l dev01
锁定的原理是在/etc/shadow密码串前面加一个感叹号!,让这个密码哈希失效,用户无论输什么密码都登不进去。对应的解锁操作也一样简洁:
bash复制sudo usermod -U dev01
sudo passwd -u dev01
查看用户当前是否被锁定,用passwd -S:
bash复制sudo passwd -S dev01
# dev01 LK 2025-02-01 0 99999 7 -1 (密码已被锁定)
输出里的LK表示locked,PS表示密码已设置可用,NP表示没设密码。运维巡检时我习惯批量看一遍所有用户的状态,挑出异常锁定的账号。
4.2 密码过期策略与chage
密码策略是很多团队最容易忽略的一块。没有过期策略的服务器,一个密码可能被用三年,一旦泄露,等于给攻击者留了一扇长期开着的大门。用chage设置密码策略非常直接:
bash复制sudo chage -M 90 -m 7 -W 15 dev01
三个参数的含义分别是:-M 90表示密码最长使用90天必须更换;-m 7表示两次密码修改之间至少间隔7天,防止用户改来改去刷掉历史;-W 15表示密码到期前15天开始提醒。查看某个用户的完整密码策略:
bash复制sudo chage -l dev01
chage -d 0的强制改密策略在2.3里已经提过,这里再补充一个实际场景:批量给一批实习生开测试机账号,为了避免他们开完账号就把密码随意分享,我通常初始化后强制首登改密,同时设好90天过期,这样即使初始密码被别人看到,过几天也失效了。
账户过期和密码过期是两件事。密码过期了用户还能改密码救回来,但账户过期是账号整个失效,用usermod -e可以精确控制:
bash复制sudo usermod -e 2025-12-31 temp_audit
到了指定日期,这个账号即便密码正确也无法登录,适合做外包人员、临时合作伙伴的到期自动失效控制。
4.3 查看系统里的登录痕迹
排查“谁动过系统”是运维常事。几个查看登录情况的基础命令必须熟:who和w看当前谁在线,last看最近成功登录记录,lastb看登录失败记录,lastlog看所有账号最近一次登录时间。
bash复制who
w
last -20
lastb -20
lastlog -u dev01
其中last读取的是/var/log/wtmp,lastb读取的是btmp,失败记录默认只有root能看。当你发现服务器被爆破时,lastb能直接告诉你攻击IP和爆破次数,这是第一手证据。
再往深一层,RedHat系的/var/log/secure和Debian系的/var/log/auth.log记录了完整的认证过程,包括sudo执行记录、SSH登录尝试、su切换等。排查用户异常行为时,我习惯先grep这个日志看时间线:
bash复制sudo grep "sudo" /var/log/secure | tail -20
这套组合拳下来,用户什么时候登录的、登录后执行了哪些sudo命令、有没有暴力破解痕迹,基本都能复原出来。这也是我坚持让团队用sudo而不用su的原因:只有sudo才有这么清晰的审计日志。
5. 系统的日常体检与资源限制:用户能碰多少东西
5.1 快速摸清系统家底
用户管理做得再细,如果对系统本身一无所知也是白搭。我每次接手一台新服务器,第一轮体检固定看这几个命令的输出:
bash复制cat /etc/os-release
uname -r
lscpu | head -10
free -h
df -h
/etc/os-release告诉你发行版名称和版本号,决定了你该用yum还是apt;uname -r看内核版本,排查内核相关问题时必须知道;lscpu、free、df分别是CPU、内存、磁盘的情况。搞清楚家底之后再动手装环境、配服务,心里才不慌。另外提一句,有些发行版比如银河麒麟,虽然换了皮肤和软件源,但底层还是Linux那一套,用户管理、权限、服务的操作逻辑完全通用,密码重置走单用户模式救援入口也一样能解决,不要被桌面环境吓到。
5.2 ulimit与limits.conf:用户能消耗多少资源
系统放给了用户,但用户不能无限制消耗系统资源。一个失控进程把文件句柄耗尽、内存吃满,导致整个服务器雪崩的例子我见过太多次了。所以每个用户能开多少文件、多少进程、占多大内存,Linux都有一套限制机制,核心命令是ulimit。
bash复制ulimit -a
输出里比较关键的几个:open files是单个进程能打开的文件数,max user processes是单个用户能创建的进程数。如果程序报Too many open files,基本都是这个值太小。临时修改:
bash复制ulimit -n 65535
但ulimit只对当前shell会话生效,关了终端就失效。要永久生效,得写到/etc/security/limits.conf:
bash复制* soft nofile 65535
* hard nofile 65535
第一列填用户名或组名,*表示所有用户;soft是软限制,到达后警告但仍可用;hard是硬限制,到达后直接拒绝。改完limits.conf需要重新登录会话才生效。顺带说一句,在AIX平台上查看用户限制用的是lsuser -a fsize等命令,或者limits -a,思路跟Linux的ulimit一致,只是命令风格不一样,跨平台运维时别记混了。
5.3 服务与进程的控制逻辑
“用户控制程序”这个说法听起来很泛,落到实操无非是两点:用systemctl管理系统服务,用ps/top管理进程。
bash复制sudo systemctl status nginx
sudo systemctl start nginx
sudo systemctl enable nginx
sudo systemctl restart nginx
systemctl有两个概念容易混:start是立即启动,enable是设置开机自启。很多新手部署完nginx只start不enable,机器一重启,服务没起来,一脸懵。正确流程是start和enable都要。
如果你想指定某个服务以某个系统用户身份运行,以systemd服务为例,在service文件里加User和Group字段就行:
ini复制[Service]
User=myapp
Group=myapp
ExecStart=/usr/local/bin/myapp
配合系统用户账号,能够把服务进程权限尽量收紧。进程查看则主要通过ps和top,定位高CPU高内存进程时,top里的USER列能直接告诉你这个进程属于哪个用户,再顺着用户ID去排查是哪个业务。
6. 文件权限:Linux系统里最容易“被拒绝”的地方
6.1 权限位的真实含义
如果说用户和组是身份的划分,文件权限就是这个身份能干什么事的界定。很多人遇到Permission denied就慌,其实只要看懂了权限位,90%的问题都能自己解决。
bash复制drwxr-xr-x 2 root root 4096 Feb 25 10:00 /opt/app
-rw-r--r-- 1 root root 512 Feb 25 10:00 /opt/app/a.conf
第一列有10个字符,第1位是文件类型,d表示目录,-表示普通文件,l是软链接。后面9个字符每3个一组,分别代表属主、属组、其它用户的rwx权限。r是读,w是写,x是执行。这里最容易混淆的是目录的x权限:文件的x表示能否执行程序,目录的x表示能否进入这个目录。一个目录哪怕有r权限但没有x权限,ls能看到文件名列表,但cd不进去,文件也读不了,这种状态很诡异,排查时容易被绕晕。
6.2 chmod、chown的正确用法
改权限用chmod,有两种写法。数字法最直观:r=4、w=2、x=1,三个值相加。rwx就是7,r-x是5,r--是4。所以755表示属主rwx、属组rx、其它rx,这是程序文件最常见的权限;644表示属主rw、属组r、其它r,这是配置文件最常见的权限。
bash复制sudo chmod 755 /opt/app/run.sh
sudo chmod 644 /opt/app/a.conf
符号法适合局部修改,比如只给属主加执行权限:
bash复制sudo chmod u+x /opt/app/run.sh
改属主和属组用chown:
bash复制sudo chown dev01:dev01 /opt/app/data.txt
sudo chown -R dev01:dev01 /opt/app
-R是递归,处理目录下所有文件时用。实际操作中我遇到最多的问题就是“为什么我创建的文件别人访问不了”,十有八九是umask和属主没搞对,下一节专门讲umask。
6.3 umask对新建文件的影响
很多人不知道,你新建的文件权限不是“系统默认的”,而是“系统默认值减去umask”,更准确地说是用默认权限位和umask取反值做按位与。系统对普通文件的默认权限是666,对目录是777,umask的作用就是把某些权限位“屏蔽”掉。
看当前umask:
bash复制umask
# 0022
022屏蔽了组和其它用户的写权限,所以普通文件实际是666减掉022那部分写位,得到644;目录则是777减掉022,得到755。这解释了为什么你touch出来的文件默认是644,但你要给脚本加执行权限必须手动chmod +x。
如果希望团队新建的文件默认不给其它用户读,可以把umask改成027:
bash复制umask 027
永久修改写到/etc/profile或者/home/用户名/.bashrc里,这两种文件分别影响全局和单用户。改umask时注意,别把组权限清得太狠,否则同一个项目组的同事之间互相没法读写文件,协作就出问题了。
6.4 “权限被拒绝”类问题的排查思路
“用户拒绝访问内存文件权限怎么办”这类问题,网上问的人很多,但答案往往不通用。我根据自己的排查习惯,总结了一条固定链路,按顺序查基本能定位:
第一步,看文件和目录的权限位,确认用户或用户所在组是否具备对应权限。第二步,用ls -ld确认路径上的每一级目录是否有x权限,很多时候文件本身有权限,但其中一级目录的x权限缺失,导致路径无法穿过。第三步,看属主属组,确认文件是不是归当前用户所有,不是的话考虑chown或加组。第四步,检查SELinux或AppArmor,在RedHat系系统上先执行getenforce看是不是Enforcing状态,再用ausearch或audit2why看被拒记录,这块坑最多,一条SELinux规则能让你折腾整晚。第五步,查看文件系统挂载选项,mount命令输出里如果有noexec、nosuid、nodev之类的标志,说明该目录下的程序不能执行或者不能改权限,这常见于内存盘、共享存储或特定安全分区。
举一个真实的例子:有次同事把网站目录设置为700,独属root,但Web服务是以nginx用户运行的,结果页面全部403。排查时第一眼ls -l就看到了问题:目录权限是drwx------,nginx用户既不在属主位也不在组位,直接被拒。解决办法是chown -R nginx:nginx目录,或者chmod改为755,让nginx能读。这类问题一旦掌握了排查链路,基本几分钟就能搞定,怕就怕拿到问题不分析,盲目chmod 777,那是给系统埋雷。
我自己遇到权限类问题时,习惯严格遵守上面的顺序,从不跳过SELinux检查那一环。很多新手把权限调成了777问题依旧,其实压根就是SELinux在拦截,白白绕了一大圈。记住:777能解决的是“基础权限不够”,但解决不了SELinux和挂载选项带来的拦截,滥用777还会让整个系统失去权限隔离的意义。权限排查这个能力,是Linux用户从入门到能独当一面的分水岭。
