Linux用户管理实战:从useradd到权限控制与安全审计

Linux用户管理实战:从useradd到权限控制与安全审计 1. 用户管理到底在管什么我刚接触Linux那会儿对用户管理的理解就停留在useradd和passwd这两个命令上。直到有一次线上服务器被拖库排查下来发现是某个离职员工的账号还挂在sudo组里才意识到用户管理绝不只是“建账号、设密码”这么简单。Linux是一个多用户、多任务的操作系统所有进程、文件、资源分配都跟用户身份绑定。用户管理本质上是做两件事一是身份识别让系统知道“你是谁”二是权限控制决定“你能碰什么、能改什么、能跑什么”。这两件事贯穿了服务器的整个生命周期从初始化环境到日常运维再到安全审计每一环都绕不开。这篇文章我把用户管理从命令到原理、从创建到删除、从单机到批量完整拆开来讲。适合刚入行的运维新手、准备Linux面试的求职者也包括那些已经用了一年半载Linux、但一直靠“复制粘贴命令”过日子的朋友。看完你不仅能敲得出命令还能说出每条命令背后的逻辑遇到问题也知道往哪个方向排查。顺便说一句文中涉及的命令我都在CentOS 7.9和Ubuntu 20.04上实测过两者在个别参数上略有差异我会在对应位置标注出来。2. 创建用户的完整姿势与底层逻辑2.1 useradd 参数拆解不只是“加一个人”这么简单useradd是用来创建用户的命令但它远不止“创建一个用户名”而已。一个用户的诞生背后牵扯到家目录、UID/GID、Shell环境、密码策略、账号有效期等一系列属性。先看一个最常用的完整创建命令useradd -u 1050 -g devgroup -G wheel,docker -d /home/zhangsan -s /bin/bash -c Zhang San zhangsan逐个拆解-u 1050手动指定UID。生产环境里为了统一权限和备份迁移经常需要固定UID。如果不指定系统会从上一个用户UID的基础上自动加1通常从1000开始。-g devgroup指定主组 primary group。用户创建后默认会以这个组作为自己的初始组文件创建时的默认属组就是它。-G wheel,docker指定附加组 supplementary groups。一个用户可以同时属于多个组附加组最大的价值是权限叠加。比如把用户加进wheel组在很多发行版里就等同于授予了sudo权限CentOS和RHEL是这种设定。-d /home/zhangsan指定家目录路径。默认是/home/用户名但如果你希望某个用户的家目录放在/data/下面就可以用这个参数改掉。-s /bin/bash指定登录Shell。如果用户只需要跑服务、不需要交互式登录可以设成/sbin/nologin这样用户无法通过SSH直接登录到Shell是一种常见的安全加固手段。-c Zhang San备注信息一般写用户的真实姓名或用途方便管理。创建完用户之后紧接着要做的是设置密码passwd zhangsan执行后会交互式地要求输入两次密码。这里有个很多新手踩过的坑passwd不带用户名的时候修改的是当前登录用户自己的密码不是别人的。所以一定要带上用户名。如果是在脚本里批量创建用户交互式输密码就很麻烦可以用下面这种方式echo zhangsan:MyPass123 | chpasswd或者在某些发行版上用passwd --stdin zhangsan--stdin参数在CentOS上是支持的但在Ubuntu上不支持Ubuntu上请使用chpasswd。2.2 创建用户时系统默默做了什么你以为useradd zhangsan就只创建了一个账号其实系统在你敲下命令的瞬间干了一连串事情写入/etc/passwd这是用户信息的主数据库每一行对应一个用户包含用户名、密码占位符、UID、GID、备注、家目录、Shell七个字段。写入/etc/shadow这里存放加密后的密码哈希和密码策略如过期时间、最小修改间隔、警告天数等。普通用户没有读取权限只有root能看。写入/etc/group登记用户所属的组信息。创建家目录默认参考/etc/skel目录的模板这个目录下的隐藏文件如.bashrc、.bash_profile会自动复制到用户的新家目录里作为初始化的Shell配置。设置家目录权限一般设为700意味着只有用户自己可以进入和查看自己的家目录。这也是为什么有些时候你手动mkdir了一个家目录并chown给它但登录进去发现命令行提示符颜色怪怪的、命令补全不好使——因为缺少了/etc/skel里那一套隐藏配置文件的初始化。如果你创建用户时用了-M参数不创建家目录后来又想补上可以手动执行mkdir -p /home/zhangsan cp -a /etc/skel/. /home/zhangsan/ chown -R zhangsan:devgroup /home/zhangsan chmod 700 /home/zhangsan这套手动流程我用过不止一次每次都能救急。2.3 密码策略和账号有效期别让密码“永不过期”很多初学Linux的人在设置密码时只关心“能不能登录”而忽略了密码策略。等服务器被暴力破解了才后悔当初没设置过期周期。密码策略相关的参数都在/etc/shadow的密码字段后面是一串冒号分隔的数字。用chage命令可以方便地管理# 强制用户首次登录后立即修改密码 chage -d 0 zhangsan # 设置密码有效期为90天过期前7天开始提醒 chage -M 90 -W 7 zhangsan # 查看用户的密码过期信息 chage -l zhangsan首次登录强制改密码这个操作在批量创建账号时非常常用尤其是给新员工开账号的流程。管理员设一个临时密码用户第一次登录就会被系统要求改成自己的密码避免管理员知道所有人的密码也避免临时密码长期有效带来的安全隐患。另外说一下/etc/login.defs这个文件它定义了系统层面的密码策略默认值比如PASS_MAX_DAYS、PASS_MIN_DAYS、UID_MIN等。如果你希望所有新用户的密码默认90天过期直接改这个文件就行比每条useradd后面都跟一个chage省事得多。3. 用户组、权限边界与文件归属3.1 groupadd 与 gpasswd把“人”归类才能管得清爽用户一多一个个授权就变得不可维护。正确的做法是先把用户分组再给组授权。创建用户组的命令很简单groupadd -g 2000 devgroup把用户加进组可以用gpasswdgpasswd -a zhangsan devgroup把用户移出组gpasswd -d zhangsan devgroup这个方式有个好处gpasswd -a命令对用户当前已登录的会话也生效而直接改/etc/group文件的方式则需要用户重新登录才能生效。实测中我遇到过改完/etc/group后用户说“权限还是不对”排查半天发现是缓存问题后来就统一改用gpasswd了。还有一种临时切换主组的场景。用户创建的文件默认属于他的主组但如果你想让某个用户临时以另一个组身份干活可以用newgrpnewgrp devgroup执行后当前Shell的有效组会切换成devgroup新创建的文件属组就会跟着变化。退出用exit即可。3.2 权限的精细控制从 rwx 到 ACL弄清楚了用户和组终于可以聊权限本身了。Linux的基本权限模型是rwx三组字符分别对应属主u、属组g、其他用户o。但实际运维中基本权限模型会经常“不够用”。最典型的场景文件属于devgroup组组的权限是r-x现在要让用户zhangsan对这个文件有写权限但又不想把他加进devgroup组。这时候ACLAccess Control List就派上用场了。setfacl -m u:zhangsan:rwx /data/project/config.yaml查看ACLgetfacl /data/project/config.yaml删除指定用户的ACLsetfacl -x u:zhangsan /data/project/config.yamlACL用起来确实灵活但也要注意一点ACL的优先级高于基本权限当文件设置了ACL之后ls -l看到的权限位后面会多一个号。很多新手看到这个号不知道是什么意思用getfacl查看才明白是设了额外权限。还需要特别提醒的是ACL在某些文件系统上需要额外挂载参数支持比如老版本的ext4默认支持但如果你把文件放在某些网络存储或精简文件系统上ACL可能不生效配置前先确认文件系统类型。3.3 属主和属组的修改chown 与 chgrp 的经典坑改属主属组是迟早要遇到的操作。命令本身很简单chown zhangsan:devgroup /data/project chown -R zhangsan:devgroup /data/project但我在这里踩过一个很有代表性的坑chown -R会把目录下所有文件和子目录的属主属组全部改掉这在大多数场景下是预期行为。可如果这个目录里挂载了其他磁盘分区比如/data/project下面有个mount的NFS目录chown -R会直接穿透挂载点把挂载目录里面文件的属主也给改了。严格说chown -R是否会穿透挂载点取决于具体行为和文件系统类型但很多场景下确实会发生。所以我现在的习惯是在需要递归改属主但目录里可能有挂载子目录的时候先用mount查一下挂载点或者用find排除挂载目录。另一个容易忽略的点是chown不仅可以改属主还可以只改属组。比如chown :devgroup /data/project注意冒号前面为空表示只改属组不动属主。这个写法在批量处理文件归属时非常好用不用费劲地先查当前属主是谁。4. 实战场景批量创建、权限隔离与安全下线4.1 批量创建用户脚本化操作的正确打开方式新上一批服务器或者开发团队扩编的时候一次性要创建十几个用户一条条敲命令不现实。这时候脚本化操作的价值就体现出来了。下面分享一个我用过很多次的批量创建用户脚本逻辑注意是逻辑你可以根据自己的场景改#!/bin/bash # 批量创建用户并设置初始密码 user_listzhangsan lisi wangwu for user in $user_list; do # 判断用户是否已存在 if id $user /dev/null; then echo 用户 $user 已存在跳过 continue fi # 创建用户指定附加组 useradd -G devgroup -s /bin/bash -m $user # 设置初始密码并标记为首次登录需修改 echo $user:Init12345 | chpasswd chage -d 0 $user echo 用户 $user 创建完成 done这个脚本里有几个细节值得说明id $user是在创建前做存在性检查避免重复执行时报错。chpasswd从标准输入读取“用户名:密码”比循环调passwd快得多。chage -d 0强制用户首次登录改密码防止初始密码长期有效。批量创建完成后建议把生成的用户列表导出留存方便后续审计awk -F: $31000 {print $1 $3} /etc/passwd /root/user_list_$(date %F).txt这个命令会把UID大于等于1000的用户正常创建的普通用户导出到一个带日期的文件里哪天想核对账号清单找这个文件就行。4.2 切换用户执行身份su 与 sudo 的选择用户创建好了免不了要在不同身份之间切换。最常用的两个命令是su和sudo但很多人并没有真正分清楚它们的区别和使用场景。su是切换用户需要输入目标用户的密码。如果你从root切到普通用户不需要密码但从普通用户切到root必须输入root密码。su - zhangsan注意中间有个-这个-表示同时加载目标用户的完整环境变量家目录、PATH、Shell配置等。不加-的话虽然用户名切过去了但环境变量还是原来那个用户的经常会导致“明明切换了用户命令却找不到”的诡异问题。sudo则是以其他用户身份执行单条命令只需要输入当前用户自己的密码甚至配置了NOPASSWD的话连密码都不用。最典型的用法sudo -u zhangsan ls /data/projectsudo和su的核心区别在于授权模型。su相当于把整个账号的钥匙交出去而sudo可以做到精确到“某条命令允许谁执行”。日常运维中强烈建议用sudo而不是su因为su - root一旦把root密码泄露给普通用户整个系统的安全边界就直接没了。sudo权限的配置在/etc/sudoers文件里这个文件一定要用visudo命令编辑不要直接用vim改因为visudo会做语法检查配置错误时不让你保存避免出现“sudoer文件写坏导致所有用户都无法提权”的尴尬局面。一个常见的配置# 允许 devgroup 组的用户执行所有命令 %devgroup ALL(ALL) ALL # 允许 zhangsan 免密执行 systemctl 命令 zhangsan ALL(ALL) NOPASSWD: /usr/bin/systemctl配置格式是“用户/组 主机(可以切换的身份) 命令”ALL表示不做限制。生产环境里我建议把suduers配置收窄能指定具体命令就指定具体命令别图省事直接写ALL不然万一账号被盗攻击者可以直接sudo bash拿到root shell。4.3 禁用用户与彻底删除离职场景的标准操作流程员工离职或者服务器上某个服务不再需要某个账号时正确的处理顺序是先锁定再备份最后删除。很多人上来就userdel -r万一删错了数据就找不回来了。第一步锁定账号禁止登录usermod -L zhangsan passwd -l zhangsanusermod -L和passwd -l都是锁定账号区别在于usermod -L是在密码哈希前加!而passwd -l的机制类似。用哪个都可以习惯就好。第二步如果确认不再需要保留数据再彻底删除userdel -r zhangsan这里的-r参数会同时删除该用户的家目录和邮件池。不加-r的话用户虽然没了但家目录还留着数据还在只是变成了一个没有属主的“孤儿目录”。如果用户当前有进程在运行userdel会提示user zhangsan is currently used by process xxx这时候需要先把相关进程杀掉或者用pkill -u zhangsan清理再执行删除。还有一点值得注意删除用户并不会自动删除该用户在其他地方留下的文件。如果该用户之前创建过定时任务、系统服务或数据库账号这些都需要手工确认清理。我的习惯是删除前先用find / -user zhangsan扫一遍把该用户拥有的文件列出来确认哪些要保留、哪些要清理避免删完用户后留下大量“幽灵文件”占用空间。4.4 安全下线前的审计查活跃会话与最近登录在禁用或删除用户之前先看看这个用户当前是否在线上、最近从哪登录过是一项必要的安全检查。用下面几个命令可以快速摸清情况# 当前登录在线的用户 who # 各用户最近登录记录 last # 查看特定用户的登录历史 last zhangsan # 查看所有用户的最近登录时间 lastloglast命令读取的是/var/log/wtmp文件lastlog读取的是/var/log/lastlog这两个文件如果被清空过历史记录自然会消失所以不要过度依赖它们作为唯一证据。在实际离职处理中我的标准操作流程大致是last $user确认最近登录时间和来源IP。ps -u $user查看该用户是否还有残留进程。检查/home/$user/.ssh/authorized_keys确认该用户添加过的SSH公钥这些公钥如果不清理即使删了账号公钥也可能在其他账号中被复用。锁定账号再观察一周确认没有影响后执行删除。这套流程虽然保守但能避免多数因为“急着删号”导致的事故。5. 用户管理里的经典故障排查记录5.1 用户创建成功了却无法登录这是新手最容易遇到的一个问题。可能的原因有三个密码没设置或设置失败useradd创建的用户默认是没有密码的只有设置了密码才能登录。用passwd命令或chpasswd补上就行。Shell设置成了nologin很多服务账号的Shell是/sbin/nologin如果你不小心把普通用户的Shell也设成了这个自然无法登录。用usermod -s /bin/bash $user改回来即可。账号被锁定了用passwd -l锁定过的账号登录时即使密码正确也会被拒绝。用passwd -u $user解锁。排查思路很简单先grep $user /etc/passwd看基本信息再passwd -S $user看账号状态基本能定位问题。5.2 sudo 提示“不在 sudoers 文件中”刚创建的普通用户执行sudo命令经常遇到这个报错zhangsan is not in the sudoers file. This incident will be reported.原因是该用户没有被授权进入/etc/sudoers配置。解决办法有两种把用户加进wheel组CentOS/RHEL默认该组有sudo权限usermod -aG wheel zhangsan在/etc/sudoers里显式添加visudo # 添加一行 zhangsan ALL(ALL) ALL我的建议是优先用组的方式后续管理起来更集中。如果你给多个用户逐条加sudo权限将来要收回的时候就得一条条删非常痛苦。5.3 切换用户后命令找不到了执行su zhangsan之后发现很多原本应该有的命令比如ls、grep都提示command not found。原因基本可以断定是没加-。su和su -的区别在于后者会重新初始化目标用户的环境变量包括PATH。不加-的时候当前Shell的PATH还是原来用户的很多路径下的命令自然找不到。解决方式也简单直接习惯用su - zhangsan不要偷懒省掉那个短横线。5.4 用户删除了但磁盘空间没有释放某个用户离职后你用userdel -r删了账号结果df -h一看磁盘空间还是被占着。别慌这大概率是有进程还在持有已删除文件造成的。进程在运行时会打开文件句柄即使文件被删除只要句柄没释放磁盘空间就不会真正释放。可以用lsof找到这些进程lsof L1 | grep deleted看到结果后确认是哪些进程在占用重启或杀掉相关进程后磁盘空间就会自动回收。这个坑我在线上环境遇到过当时删了一个日志账号删完发现/home分区还是满的排查了好久才意识到是有个残留的日志采集进程还开着旧文件句柄。所以建议大家在删除用户前先确认有没有该用户相关的进程在跑宁可多观察几天也别急着删到家目录。5.5 常见问题速查表症状可能原因排查命令解决办法无法登录账号锁定或密码错误passwd -S $userpasswd -u $user解锁无法登录Shell为nologingrep $user /etc/passwdusermod -s /bin/bash $usersudo报错未加入sudoersgroups $user加入wheel组或编辑sudoers切换用户后命令缺失缺-号echo $PATH使用su - $user创建文件属主显示数字uid不存在于/etc/passwdid $user检查用户是否被误删删除用户后空间未释放进程占用文件句柄lsof L1 | grep deleted重启或杀掉相关进程修改组权限不生效用户已登录会话缓存id $user重新登录或使用gpasswd6. 用户管理中容易被忽略的File权限细节6.1 /etc/passwd 和 /etc/shadow 的区别很多用了一段时间Linux的人还是搞不清/etc/passwd和/etc/shadow分别是干什么的。简单说/etc/passwd保存用户基本信息包括UID、GID、家目录、Shell。这个文件是全局可读的任何用户都能查看。密码字段早期存在这里现在是一个x占位符。/etc/shadow保存密码哈希和密码策略只有root和拥有特定权限的组才能读取。普通用户看到的内容是!!或*不是真实的哈希值。正因为/etc/passwd全局可读所以在配置服务时切忌把明文密码或重要密钥写进去。另外如果/etc/shadow的权限被改成了普通用户可读比如644那基本等于把密码哈希拱手送人攻击者可以离线暴力破解。定期检查这两个文件的权限是一个好的习惯ls -l /etc/passwd /etc/shadow # 正常应为 # -rw-r--r-- 1 root root ... # -rw-r----- 1 root shadow ...6.2 umask 对新建文件和目录默认权限的影响用户创建一个新文件或目录时默认权限由umask决定。默认的umask值通常是022意思是去除组和其他用户的写权限所以新文件的权限是644新目录的权限是755。如果你希望同组用户能直接修改你新建的文件可以把umask改成002umask 002这样新建文件的默认权限就是664同组可写目录就是775。但要注意umask命令只对当前Shell会话生效要持久化得写进用户的~/.bashrc或~/.bash_profile里。如果整个团队统一要求umask 002可以在/etc/profile或/etc/bashrc里设置。还有一种情况文件传输或解压时权限不对。比如FTP上传的文件变成了600其他用户无法访问这通常也是目标目录或传输工具的umask配置问题排查方向可以往这边想。6.3 隐藏文件与安全不只是“点开头”而已Linux里以.开头的文件默认ls不显示所以很多人管它叫“隐藏文件”。但实质上隐藏文件并没有隐藏权限或加密内容只是不在默认列表里显示而已用ls -a或ls -Al就能看到。在用户管理场景下家目录里的.ssh/authorized_keys是重点保护对象。这个文件如果权限太宽松比如644SSH服务会直接拒绝使用该密钥文件要求你把它改成600。原因很简单如果其他用户能写这个文件他们就可以往里面塞自己的公钥从而实现无缝登录接管账号。所以检查用户家目录权限、特别是.ssh目录权限是发现后门的一个重要方式。碰到过几次“服务器被人加了SSH公钥”的事件之后我现在每次排查入侵第一件事就是全盘扫描authorized_keys文件find /home -name authorized_keys -exec ls -l {} \;如果发现某个账号的authorized_keys里多出了不明公钥基本可以判定该账号已被植入后门建议立即禁用并清除公钥。7. 一些长期实践后的管理心得Linux用户管理这块内容教科书上都有但真正把它用好靠的是每天跟服务器打交道积累下来的直觉。有几个经验我用文字写下来希望能帮你少走弯路。第一创建用户之前先想好这个账号的“生命周期”。这个账号是给谁用的用多久需要哪些权限离职/下线后怎么回收这四句话在创建前想清楚后面能省掉大量麻烦。我见过太多团队账号是随手建的权限是越加越大的最后满服务器的“僵尸账号”无人清理安全隐患极大。第二能不用root尽量不用root。日常巡检、查看日志、启动服务能用普通用户sudo解决的就不要直接su - root。我自己的习惯是登录服务器用普通用户需要执行管理命令时才通过sudo提权而且sudo的授权做得很细每条命令都有记录。这样万一出了安全事故审计日志能清楚告诉我们“是谁、在什么时间、执行了什么命令”。第三用户管理的日志审计是最后一道防线。Linux系统默认会记录很多用户相关的事件比如/var/log/secureCentOS/RHEL或/var/log/auth.logUbuntu/Debian里能看到所有登录、sudo提权、用户切换的痕迹。定期检查这些日志并配合集中式日志收集基本上能掌握服务器访问的全貌。我见过一些团队直到被入侵了才想起来看日志那时候已经晚了。不如从一开始就把日志收集做好每天花五分钟扫一眼异常登录和sudo记录远比出事后的紧急排查高效得多。最后一条建议是关于学习的别只看命令本身要把命令跟系统文件对照起来学。比如执行完useradd立刻去看/etc/passwd、/etc/shadow、/etc/group这三个文件发生了什么变化。理解了命令背后的文件读写逻辑你就会发现Linux的用户管理一点都不神秘几十个命令反反复复操作的都是这几个文件而已。这个思维模式比背一百条命令有用得多因为面试也好、实操也好真正考的是你“能不能灵活组合这些命令解决问题”而不是“背了多少条命令”。