
干了这么多年Linux运维带过不少新人也面过不少应聘者。我越来越确定一件事系统管理和用户管理不是两条独立的知识线而是同一件事的一体两面。很多人学Linux喜欢背命令今天学两个文件操作明天学三个网络工具结果遇到实际问题还是懵。比如新同事把tomcat跑在root下或者给一个普通用户配了sudo却开得跟没设一样这些都不是命令记得少的问题而是对Linux的用户权限模型缺乏整体认知。这篇东西我想换个讲法不按命令清单走而是围绕用户管理如何决定系统管理的成败这条主线把账号体系、权限边界、常见故障排查、还有面试里最容易被追问的细节串起来讲。无论你是刚接触Linux想搭一个能用的环境还是准备运维或信息系统管理工程师方向的认证考试又或者已经在生产环境里踩过几个坑想系统捋一遍都适合当一份实战向的参考来读。1. 先把Linux的人和权分清楚用户、组、权限三位一体我刚入行时有个特别大的误区觉得用户管理就是useradd加个账号系统管理就是看看磁盘和CPU。直到有一次线上服务被误删了数据排查下来发现是有人用root执行了一条写错的rm才真正明白Linux里所有系统行为背后都是某个身份在做被允许的事。所谓系统管理本质就是管理谁能用什么身份做什么事。1.1 为什么说UID是Linux世界里更真实的身份登录的时候你输入用户名但Linux内核并不认名字它只认数字——UID。用户名和UID的对应关系存在/etc/passwd里Group名和GID的对应关系在/etc/group里。你可以用一个很直观的命令验证id uid1000(zhangsan) gid1000(zhangsan) groups1000(zhangsan),4(adm),27(sudo)这里uid1000才是内核真正用来做权限判断的依据。zhangsan这个名字只是给人看的改了用户名不会改变UID所以文件归属也不会乱反过来如果你不小心改了UID那这个用户之前拥有的文件就全变成无主的了这就是一个经典的生产事故源头。系统里有一套约定俗成的UID区间理解它有助于排查问题UID范围用途说明0root超级用户内核默认放行绝大多数权限检查1-999系统账号给服务进程用的伪用户如sshd、nginx、mysql1000普通用户登录用户通常从1000开始分配65534nobody匿名/降权用户很多服务降到这个身份运行很多人问为什么我们公司服务器上的nginx用户是998而不是1000就是因为不同发行版对系统账号区间的划分不完全一样。CentOS/RHEL 7以后系统账号是1-999而Debian/Ubuntu则是1-999但普通用户起点都是1000。所以不要在不同的发行版之间假设UID完全一致做脚本或数据迁移时一定要按名字或UID显式处理。1.2 /etc/passwd、/etc/shadow、/etc/group 三兄弟的分工这三个文件是用户管理的基石任何一个被改坏系统都可能出现登录不了、服务起不来的局面。/etc/passwd每行有7个字段用冒号分隔zhangsan:x:1000:1000:Zhang San:/home/zhangsan:/bin/bash依次是用户名、密码占位符真正的密码在shadow里、UID、GID、注释信息、家目录、登录Shell。注意那个x如果这个字段为空说明这个账号没有密码某些情况下可以直接登录这也是一个安全隐患。/etc/shadow专门存密码哈希和密码策略普通用户没有读取权限只有root能看。它的字段更多常用的有密码哈希、上次修改密码时间、最短修改间隔、最长使用期限、过期前警告天数、账号失效日期。用chage命令管理这些策略比手改文件安全得多后面讲到密码安全时再细说。/etc/group保存组信息一个用户除了自己的主组primary group还能加入多个附加组supplementary groups。这里有一个新手最容易掉进去的坑如果你把用户加进docker组或sudo组但没有重新登录当前会话是不会生效的。一定要exit重新登录或者用newgrp docker切换一下否则你会怀疑自己明明加了组为什么还是权限不足。2. 用户管理的实操从useradd到usermod每一步都别想当然命令行操作看似简单但每一条命令背后都有默认行为和隐藏参数。我在面试时最爱问的一个问题是useradd和adduser有什么区别很多人答不上来或者只知道一个是命令一个是脚本。实际上useradd是系统原生命令参数固定adduser是Perl脚本会交互式问你密码、全名等信息更适合新手交互使用。生产环境批量建号我一定用useradd因为可脚本化、行为可控。2.1 创建用户时真正需要关心的参数先看一个实际场景公司来了个新同事需要给他建一个账号加入dev组给他一个自定义的家目录指定bash作为Shell同时设置密码策略90天必须改一次。# 创建用户并指定UID、家目录、Shell、附加组 useradd -u 1050 -d /data/users/lisi -m -s /bin/bash -G dev,wheel lisi # 设置初始密码chpasswd方式更适合脚本场景 echo lisi:InitialPass2024 | chpasswd # 设置密码90天过期提前7天提醒 chage -M 90 -W 7 lisi # 查看用户创建结果 id lisi grep lisi /etc/passwd chage -l lisi逐个拆解这里的设计逻辑-u 1050显式指定UID对于需要做NFS共享、或对接外部认证的场景固定UID可以避免不同机器上UID漂移导致的文件归属错乱。-d /data/users/lisi不把家目录放在默认的/home下。如果公司有独立数据盘挂载在/data把用户数据放独立分区是更合理的规划避免系统盘被撑爆。-m这个参数的意思是如果家目录不存在就创建它。用户初始化时指定后面改家目录时一般不推荐加-m因为会复制旧家目录文件过去行为容易被误解。-G dev,wheel加附加组。wheel组在CentOS上默认有sudo权限而在Ubuntu上是sudo组发行版之间又一个差异点。chage -M 90 -W 7强制90天改一次密码提前7天提醒。这是企业内部合规的常见要求比默认的永不过期安全得多。这里还想强调一个很多教程不会提的细节useradd默认的UMASK是022创建家目录的权限是755。如果你们的安全基线要求家目录是750或700要么改/etc/login.defs里的UMASK要么建号后手动chmod。别等服务上线了再回头发现别的同事能随便读你家目录。2.2 修改用户信息最容易忽略的连锁反应usermod是修改用户信息的主要工具但我见过太多人只改一个字段忽略了连锁反应# 改用户名 usermod -l newname oldname # 改家目录 usermod -d /home/newname -m newname # 改附加组注意这是覆盖式操作 usermod -G dev,dba newname重点说第三个-G是完全覆盖不是追加。如果用户原来在docker组里你执行usermod -G dev,dba zhangsan他的docker组就没了可能导致他无法操作docker命令清理环境时才发现原来能用的现在全Permission denied。如果只是想追加一个组推荐用gpasswd -a username groupname# 追加一个附加组更安全 gpasswd -a zhangsan docker另外usermod -l改名有个经典坑用户名变了但家目录和邮箱缓存未必跟着变。如果你改了用户名一定记得同步修改或移动家目录否则用户登录后会落到一个奇怪的家目录里。userdel同样有需要注意的地方# 删除用户的同时删除家目录和邮件池 userdel -r zhangsan当用户UID下还有其他进程在跑时userdel -r会提示user is currently used by process xxx此时强行删会导致文件变成无主状态。经验做法是先pkill -u zhangsan或通知用户退出确认没有进程残留再执行删除。生产环境离职账号处理我更推荐先锁账号而不是删账号哪天审计或法律需要查操作记录时还能追溯# 锁定账号禁止登录但保留数据 usermod -L zhangsan # 如果还需要强制到期 chage -E 2024-12-31 zhangsan2.3 批量创建用户的正确姿势新员工入职季一个一个useradd效率太低。我的做法是准备一个文本文件然后用脚本循环处理# users.csv 内容username:uid:group:comment zhangsan:1050:dev:Zhang San lisi:1051:dev:Li Si wangwu:1052:dev,dba:Wang Wu while IFS: read -r user uid groups comment; do useradd -u $uid -d /home/$user -m -s /bin/bash -G $groups -c $comment $user echo $user:TempPass123 | chpasswd chage -d 0 $user # 强制首次登录改密码 done users.csv关键在最后一行chage -d 0把密码最后修改时间设为0这样用户首次登录时系统会强制要求改密码。这是批量建号的必备操作能避免大量初始密码长期有效带来的安全风险。3. 权限模型深入rwx、umask、特殊权限位与sudo边界用户和组的划分只是谁是谁真正的系统管理核心是谁能对哪个文件做什么。Linux权限模型看似简单就rwx但组合起来变化很多尤其是在生产环境里排查权限问题时靠猜是猜不出来的。3.1 rwx对于文件和目录含义完全不同大多数人知道r是读、w是写、x是执行但对于目录这三个位的语义和文件不一样这是很多权限故障的根源权限位对文件的意义对目录的意义r读取文件内容列出目录下文件名w修改文件内容在目录内创建/删除/重命名文件x执行文件脚本/二进制进入目录、访问目录内文件属性举个例子如果一个目录只有r没有x你虽然能ls看到文件名列表但访问文件详情、或者cd进去都会失败。很多Nginx报403的案子排查到最后发现是目录少了x位导致进程无法穿越路径。检查权限我推荐用stat而不是ls -l因为ls在某些alias环境下输出格式不稳定stat -c %a %U:%G %n /data/project另外要注意的是权限是最短路路径累加的。比如一个文件/data/project/log/app.log权限是640但你能否读到它取决于你对/data、/data/project、/data/project/log每一层目录是否都有x权限。只盯着最后那个文件的权限解决不了问题。3.2 umask、SUID、SGID和Sticky Bit生产环境里的真实用法umask决定了新建文件和目录的默认权限。公式是文件默认权限 666 ~umask目录默认权限 777 ~umask。如果你的umask是022新建文件就是644、目录就是755。运维批量部署时经常需要让同组同事协作编辑项目文件这时把umask设为002是常见做法# 临时设置 umask 002 # 永久设置写入profile或/etc/profile.d/umask.sh echo umask 002 /etc/profile.d/umask.sh然后配合chmod gsSGID使用可以让新建文件自动继承目录的所属组而不是创建者的主组。这样团队协作时大家互相覆盖文件不会因为组不一致而频繁报权限错误。特殊权限位的识别也是面试和实战高频点SUID4000文件执行时以文件属主身份运行而不是执行者身份。典型例子是/usr/bin/passwd普通用户改密码时需要有写/etc/shadow的权限正是SUID让passwd以root身份运行。但SUID也是提权攻击的重灾区能用find / -perm -4000定期扫描系统里的SUID文件发现异常项就要警惕。SGID2000文件执行时以文件所属组运行目录设置了SGID后新文件自动继承目录组。Sticky Bit1000典型是/tmp。在Sticky目录下只有文件属主、目录属主或root能删除文件其他人就算有写权限也删不了别人的文件。设置方法chmod 4775 file、chmod 2770 dir、chmod 1777 /tmp。但实际生产里我更推荐用符号模式可读性更强chmod us /usr/local/bin/script.sh chmod gs /data/team_project chmod t /data/shared_tmp3.3 sudo配置的艺术授权最小化别图省事很多生产事故不是恶意破坏而是sudo权限给得太宽。visudo改/etc/sudoers时你至少要遵守三个原则原则一尽量用命令白名单不要直接给ALL。# 坏例子 zhangsan ALL(ALL) ALL # 好例子只允许管理nginx服务 zhangsan ALL(root) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx原则二NOPASSWD要慎用。方便是方便但意味着只要有人拿到你的会话就能静默执行高危命令。我的建议是重启、reload这类对业务连续性影响大的命令可以免密但涉及用户管理、磁盘格式化、网络配置的命令一定要保留密码验证。原则三对提权路径要有认知。很多初学者以为只给了/bin/cat权限他可以看shadow但这不算提权。错。只要能cat /etc/shadow就能拿哈希离线爆破只要能执行vim:!bash就能拿到root shell。所以授权命令时凡是能执行任意命令的编辑器、以及能读敏感文件的命令都要在清单里排除或严格控制。顺便说一句面试时聊到提权很多候选人第一时间想的是内核漏洞。但实际生产里最常见的提权路径其实是配置不当的sudo规则、暴露的SUID文件、以及可写的服务配置文件。先把这些基线检查做好比天天追着CVE打补丁更能降低真实风险。4. 系统管理的日常从系统信息收集到进程与服务排查用户和权限的框架搭好了接下来就是在系统管理里怎么用。日常运维里贴身的命令不需要太多但每一条都要用对时机。4.1 系统概览第一时间判断机器状态接到报警你第一件事不是去看业务日志而是先确认系统本身是否健康。我的标准流程是# 查看内核和发行版信息 uname -a cat /etc/os-release # 查看负载和CPU占用 uptime top -bn1 | head -15 # 查看内存 free -h # 查看磁盘 df -hT iostat -x 1 3 # 查看系统日志中的硬件错误 dmesg -T | grep -iE error|failed | tail -20uptime的load average有三个数字1分钟、5分钟、15分钟很多人问到底看哪个。我的判断逻辑是短时间负载高可能是瞬时任务如果15分钟负载也一直高于CPU核数那才是真有问题。比如一台4核机器load拉到8持续15分钟基本可以断定有进程在抢CPU。4.2 进程管理的核心技能找进程、看连接、理依赖进程管理的痛点不是杀掉进程——kill -9谁不会——而是找到正确的进程以及判断它能不能杀、杀了会有什么连锁反应。最常见的场景端口被占。比如你重启Nginx发现bind() to 0.0.0.0:80 failed常规操作是# 查谁占了80端口 ss -lntp | grep :80 # 或者用lsof需要安装 lsof -i :80拿到PID之后先看这个进程的启动时间和父子关系再判断要不要动ps -o pid,ppid,user,lstart,cmd -p 12345 pstree -p 12345生产环境一个血泪教训是不要只盯着PID操作要看清PPID。如果你的服务是supervisor或systemd拉起来的你kill -9掉子进程守护进程马上又拉起一个新进程正确的做法是让systemd/supervisor来停服务systemctl stop nginx # 或 supervisorctl stop nginx如果实在需要手动kill也应该先kill默认SIGTERM优雅退出等几秒看进程是否还在再上kill -9。一上来就-9数据库这类进程可能丢数据。进程排查还有一个高频需求看某个进程的CPU或内存占用异常。这时候推荐用top进入交互模式按PCPU排序、M内存排序或者更快的方式ps aux --sort-%cpu | head -10 ps aux --sort-%mem | head -104.3 systemd现代Linux的服务管理底座聊systemd绕不开的问题是很多老运维对它又爱又恨。爱的是依赖管理、自动重启、资源隔离这些能力恨的是它改变了传统/etc/init.d脚本的习惯。但既然主流发行版都默认systemd那还是得扎扎实实掌握。一个最小可用的service单元文件长这样# /etc/systemd/system/myapp.service [Unit] DescriptionMy Custom Application Afternetwork.target mysqld.service Wantsnetwork-online.target [Service] Typesimple Usermyapp Groupmyapp WorkingDirectory/data/myapp ExecStart/usr/bin/java -jar /data/myapp/myapp.jar --spring.profiles.activeprod Restartalways RestartSec5 EnvironmentJAVA_OPTS-Xms512m -Xmx1024m LimitNOFILE65535 [Install] WantedBymulti-user.target这里几个关键点UsermyappGroupmyapp服务用专门的低权限用户运行这是系统管理和用户管理交叉的核心实践。生产环境里用root跑应用是巨大的风险一旦应用被入侵攻击者直接拿到root。Restartalways进程崩溃自动拉起。但注意RestartSec别设0否则进程频繁崩溃会陷入快速重启死循环把CPU打到100%。LimitNOFILE65535很多Java应用高并发时报Too many open files不是代码bug是systemd默认的LimitNOFILE只有1024。在service文件里提升这个值比修改/etc/security/limits.conf更直接——因为systemd管理的进程不读取limits.conf。这是个非常隐蔽的坑。单元文件写好后systemctl daemon-reload systemctl enable myapp systemctl start myapp systemctl status myapp排查服务起不来的问题优先看journalctl -u myapp -n 100 --no-pager不要傻傻地翻/var/log/messagessystemd的journal已经把服务的stdout、stderr、日志都收集好了。5. 高频故障实战用户权限引发的诡异问题和排查链路这一节我放三个真实场景都是我在生产环境遇到过的用户管理引发系统管理故障的典型案例。每个都按排查链路来讲而不是直接给结论你们以后遇到类似问题可以照方抓药。5.1 场景一Nginx突然403排查到底部才发现是一路径权限问题现象Nginx配置和上周一样什么都没改但今天访问某个静态资源目录全部403。排查链路先确认是Nginx层面的返回还是系统层面的拒绝。curl -I http://localhost/static/xxx.png看到403说明请求已经到Nginx了。tail -f /var/log/nginx/error.log看到Permission denied说明Nginx worker进程没有权限读文件。ps aux | grep nginx看worker进程是哪个用户跑的。假设是nginx用户。namei -l /data/www/static/xxx.png这条命令会列出路径上每一层的权限一下子就能定位是哪一层目录卡住了。namei -l /data/www/static/xxx.png f: /data/www/static/xxx.png drwxr-xr-x root root / drwxr-xr-x root root data drwx------ root root www drwxr-xr-x root root static -rw-r--r-- root root xxx.png看到问题没有/data/www的权限是700只有root能进。很可能是有同事为了防止别人看这个目录执行了chmod 700 /data/www结果把Nginx的nginx用户挡在外面了。修复chmod 755 /data/www # 或更严谨保持归属只加组权限 chown nginx:nginx /data/www chmod 750 /data/www教训权限设置一定要考虑路径上每个使用者的可达性。对目录收紧权限前先想想有哪些进程、哪些用户需要穿越这个目录。5.2 场景二新用户登录后Shell提示符变成$敲什么都没补全现象新创建的账号登录后提示符不是[userhost ~]$这种彩色格式而是光秃秃的$Tab补全没有方向键也不能翻历史。排查链路输入echo $SHELL返回/bin/sh而不是/bin/bash。说明登录Shell不是bash。grep username /etc/passwd发现用户Shell字段是/bin/sh。为什么建号时会变成/bin/sh大概率是useradd时没有指定-s /bin/bash而系统默认Shell不是bash。修复usermod -s /bin/bash username重新登录后提示符和补全都正常了。延伸还要检查一下/etc/skel目录。用户家目录里的.bashrc、.bash_profile等文件都是从这个模板目录复制来的。如果/etc/skel里没有.bashrc就算Shell是bash提示符和alias依然不完整。很多发行版的/etc/skel默认内容不一样批量建号前要把skel先规整好。5.3 场景三文件删不掉提示Operation not permitted现象root用户要删除一个文件竟然提示Operation not permitted。排查链路新手第一反应是权限不够但root怎么可能权限不够。用lsattr检查文件属性。发现文件有iimmutable属性。这是chattr i加上的不可修改标志即使root也不能改或删必须先解除。lsattr file.txt chattr -i file.txt rm file.txt教训很多加固脚本会用chattr i保护关键文件比如/etc/passwd、/etc/shadow但当你想合法修改这些文件时会一头撞上Operation not permitted。系统管理员的工具箱里不能只有chmod还有chattr、lsattr这些第二层权限工具。延伸chattr a只允许追加、不允许覆盖和删除对日志文件特别有用。但要注意有些服务比如logrotate需要删除或重命名旧日志文件a属性会导致logrotate失败所以加固时要综合考虑日志轮转策略。6. 命令之外信息收集、文档习惯和面试/考试中的高频追问用户管理和系统管理做到一定阶段你会发现瓶颈不再是不会敲命令而是排查思路不够系统。这里结合信息系统管理工程师方向的学习重点以及我面人时的关注点分享几个超纲但很实用的维度。6.1 一切皆文件用/proc和/sys理解系统状态面试时我常问一个问题不用top怎么查看一个进程的CPU使用率和运行状态能答出cat /proc/PID/stat的人不多能讲清楚的人更少。实际上/proc目录是Linux暴露内核状态的虚拟文件系统每一个进程都对应一个/proc/PID目录。几个常用文件/proc/cpuinfoCPU详细信息/proc/meminfo内存使用情况比free更底层/proc/loadavg系统负载/proc/PID/environ进程的环境变量/proc/PID/fd/进程打开的所有文件描述符排查文件删了但磁盘空间没释放的经典手段就是靠/proc# df显示磁盘满了但du找不到大文件 lsof | grep deleted # 或 ls -l /proc/*/fd/* 2/dev/null | grep deleted找到占用已删除文件的进程重启或让进程重新打开日志文件磁盘空间就释放了。/sys则暴露内核设备和驱动的配置接口比如调优TCP参数时修改/sys/kernel/mm/transparent_hugepage/enabled、或者设置磁盘调度算法时写/sys/block/sda/queue/scheduler。注意这些是运行时配置重启后失效想持久化要到/etc/sysctl.conf或/etc/udev/rules.d里设置。6.2 学会写文档运维的命脉是可追溯Linux命令再熟如果系统改了什么没记录三个月后你自己都说不清这台机器上跑的是什么版本的配置。我的习惯是每个项目维护一份CHANGELOG记录每次变更的时间、操作人、变更内容、原因、回滚方案。这不是公司逼着写的流程文档而是自己救命的工具。举个例子某次线上故障需要回滚Nginx配置如果没有记录上一版配置文件备份在哪、当时改了什么线上排查会非常被动。我现在每改一个关键配置前都要先备份cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak.$(date %F_%H%M%S)然后修改测试再记录到变更文档。这个习惯养成了就不会再出现改完连自己都忘了改了啥的尴尬。6.3 面试和认证考试常问的几个为什么结合信息系统管理工程师这类考试的常见考点和我面人时的提问习惯下面几个问题值得深入理解问常用的用户管理命令有哪些分别有什么作用至少要能脱口而出useradd、usermod、userdel、passwd、chage、groupadd、groupmod、groupdel、gpasswd、id、who、w、last。面试时我会追问用户锁定用哪个命令答案是usermod -L或passwd -l解锁对应usermod -U或passwd -u。问如何查看Linux系统的基本信息uname -a、cat /etc/os-release、lscpu、free -h、df -hT、hostnamectl。要注意区分发行版信息和内核信息。问如何排查服务端口被占用ss -lntp推荐或netstat -tlnp老命令。然后ps -fp PID看进程详情。这里面试官容易追问如果端口是TIME_WAIT状态会不会影响新连接一般不会TIME_WAIT是主动关闭连接的一方产生的正常状态除非量特别大导致连接表耗尽。问chmod 和 chown 的区别chmod改权限位rwxchown改属主和属组。生产里常见组合是chown -R user:group directory配合chmod -R gw directory把目录交给某个组协作。问如何防止某个用户登录方式很多usermod -L锁定、chage -E设置过期、usermod -s /sbin/nologin改成不可登录Shell。区分点在于锁定账号后还能不能su切换到该用户、nologin对FTP/SFTP是否生效这些都是隐藏的知识点。6.4 从会命令到会排障把知识串成体系最后说说我个人对Linux系统管理和用户管理这个主题的理解。刚学的时候我也是一边学ls、cd一边背useradd、passwd学得零零散散。后来带我的老工程师跟我说了一句话我到现在都记得你学命令不是为了敲命令是为了在出问题的时候能用这些命令拼出一条排查路径来。从那以后我调整了学习方法每学一个命令都问自己三个问题这个命令能帮我确认系统当前什么状态如果某个服务出问题了我该用哪些命令组合去定位这个命令的输出里哪些字段是真正有判断价值的比如学free -h不只是看总内存和已用内存还要关注available——它是在不触发swap的情况下还能分配多少内存的真实估算值。学df -h不只是看空间剩多少还要结合du -sh和lsof | grep deleted去判断空间为什么满。学ps aux不只是看PID还要能把%CPU、%MEM、STAT状态比如D表示不可中断睡眠通常和IO有关Z是僵尸进程串起来解读。这种思维方式才是系统管理四个字的真正含义不是管理几条命令而是管理一台机器的整体状态不是被用户管理问题牵着鼻子走而是通过用户管理把权限边界理清楚让系统管理更从容。我招人的时候其实不太在意候选人背了多少条命令。我更愿意给一个真实故障的日志片段让他讲讲排查思路。能说出先看进程、再看网络、再看日志、再看权限这种次序感的人通常比那些命令大全背得滚瓜烂熟的人更能扛事。希望这篇东西能帮你把用户管理和系统管理这两块知识真正串起来而不只是又多收藏了一份命令清单。