☰
机房Linux用户管理实战:从useradd到userdel的完整运维指南
2026/10/15 5:44:51 网站建设 项目流程

机房这活儿干久了你就发现,最不起眼的“加个账号”“删个账号”往往最考验功力。前阵子某IDC托管机房新来了两个运维,我给他们开权限、配密钥、设过期时间,顺手清了一批半年前离职同事的僵尸账号。弄完之后对方技术负责人问我,你们“删用户”是怎么做到连 /tmp 里的临时文件、crontab 残留都一起清干净的?我说这就是机房用户管理的门道——从 useradd 到 userdel,每一步都有讲究,尤其是批量、审计、权限边界这三个方面,踩过坑的人自然懂。

这篇文章不聊虚的,就把【机房】环境(其实就是大批量Linux服务器、多租户托管、多运维协作)下添加和删除用户这件事,从需求拆解、命令实操、批量脚本到排错经验整个捋一遍。无论是刚接手机房的新人,还是想规范运维流程的团队,都能直接抄作业。

1. 机房账号管理到底在管什么

1.1 为什么机房环境下的用户管理比普通服务器更敏感

普通服务器加个人,useradd 一敲,密码一设,完事。但机房环境完全不同。先说规模:一个机柜几十台服务器,一个机房上百台,跨多个机房的话上千台也正常。每台机器上可能有多个运维、多个业务代维、甚至第三方硬件巡检人员的账号。用户身份一多,权限边界就必须非常清楚。

再说风险:机房服务器通常直连核心业务,账号一旦失控,轻则配置被人乱改,重则数据泄露、被植入后门。我见过某团队给外包代维开了一个带 sudo 权限的账号,项目结束忘了删,半年后那台机器被扫出异常登录,最后排查发现就是旧账号的弱密码没清。所以机房里的账号管理本质上不是“会不会敲命令”的问题,而是“账号生命周期管理”的问题:创建时有没有规范?使用时有没有监控?删除时有没有清干净?这三件事是连在一起的。

1.2 机房用户管理最常见的使用场景

我粗略梳理了一下,机房环境里跟“添加/删除用户”相关的场景大概就这几类:

  • 新员工或新运维入职,需要开通服务器登录权限。
  • 外包代维、硬件厂商巡检人员临时需要操作权限,用完即销。
  • 业务扩缩容,需要为应用创建专属运行账号(不是人,是服务账号)。
  • 员工离职或项目结束,需要及时回收账号、清理所有痕迹。
  • 统一批量管理,比如几十台机器要同时加一个人或者删一个人。

每一种场景对“添加”和“删除”的要求都不一样。临时巡检账号可能只需要从今天起生效,有效期一周,到期自动锁定;服务账号则要求不能登录shell、不能有交互式密码登录、只能跑指定服务。这些在实操里的体现,就是 adduser / useradd / usermod / chage / userdel 这些命令的具体参数选择。下面我分两大部分详细拆。

2. 添加用户的完整实操流程

2.1 创建用户之前:先想清楚账号要赋予多大权限

很多人一上来就 useradd,这是机房操作最忌讳的。我习惯先填一份“账号开通确认单”,哪怕是给自己机房内部用一个简易表格。确认单上就三个问题:这个人是谁?他的职责范围是什么?他在服务器上需要用到哪些命令?

这决定了创建用户时的几个关键参数。比如他只是看看日志、重启一下服务,那给普通用户 + 几个白名单命令的 sudo 权限就足够了;如果他是核心网络和系统负责人,可能需要完整 sudo 权限。另外还必须确认他是长期在机房驻场的,还是偶尔远程登录。如果偶尔远程登录,那就应该在创建时加上账号过期时间,从源头杜绝“权限永久挂账”的状态。

这个步骤看起来麻烦,实际上能帮你避免至少两类问题:一是权限开太大导致事故,二是后续删除用户时根本不知道这个账号当初是干嘛的。

2.2 添加用户的具体命令与参数详解

我以 CentOS / Rocky Linux / Ubuntu 主流环境为例说一下标准实操。

# 最简单的一个添加命令,但参数含义必须搞清楚 sudo useradd -m -s /bin/bash -c "张三 - 系统运维" zhangsan # 设置初始密码(或直接禁用密码仅用密钥) sudo passwd zhangsan

命令拆解:

  • -m:自动创建家目录/home/zhangsan。不加这个参数,useradd 在多数 Linux 发行版中不会创建家目录,用户登录后有概率直接落在/根目录,一堆临时文件写进去,非常脏。
  • -s /bin/bash:指定登录shell。如果这个账号是服务账号、不需要人登录,应该改成-s /usr/sbin/nologin或/sbin/nologin,从根源上禁止交互式登录。
  • -c "备注":一定要写备注。机房几百个账号,没备注就等于没账号,没人知道它是谁的,将来删除时也没人敢动。
  • passwd zhangsan:设置密码。但机房环境强烈推荐密钥登录,后面我会单独说。

如果是要给用户加附加组,比如加入docker组或wheel组(CentOS的sudo组):

sudo useradd -m -s /bin/bash -G wheel,docker -c "张三 - 系统运维" zhangsan

这里注意-G和-g的区别:-g是设置主组,-G是附加组。把用户加入wheel组不代表用户一定能 sudo,你还得确保/etc/sudoers或/etc/sudoers.d/里配了%wheel ALL=(ALL) ALL。建议所有 sudo 策略都通过/etc/sudoers.d/下的独立文件管理,不要直接改/etc/sudoers。

再给一个更复杂的场景:临时账号指定有效期。比如给某硬件厂商工程师开一个账号,他只需要下个月一周的巡检窗口:

# 创建账号并指定账户过期日期 sudo useradd -m -s /bin/bash -e 2025-07-01 -c "硬件巡检临时账号" it_audit # 密码过期时间,强制他首次登录改密码 sudo chage -d 0 it_audit # 查看账号有效期确认 sudo chage -l it_audit

-e参数对应/etc/shadow里第8个字段,指定的日期一过,该用户就无法登录,哪怕密码没有变。chage -d 0则是要求首次登录必须修改密码,防止运维把初始密码告诉对方之后自己忘了回收。有的发行版 useradd 不带-e参数(比如老版本BusyBox环境,或者synology那是另一套),就需要用usermod -e来补,效果一样。

2.3 密钥登录配置:机房基操中的基操

密码登录在机房环境里不安全因素很多,容易被暴力破解,也容易在交接时泄露。所以我在机房加人,十次有八次直接走密钥登录。

操作流程是这样的:

# 1. 先把用户创建出来 sudo useradd -m -s /bin/bash -c "张三 - 系统运维" zhangsan # 2. 创建.ssh目录并设置正确权限 sudo mkdir -p /home/zhangsan/.ssh sudo chmod 700 /home/zhangsan/.ssh # 3. 把对方的公钥写进 authorized_keys echo "ssh-ed25519 AAAA... zhangsan@somehost" | sudo tee /home/zhangsan/.ssh/authorized_keys sudo chown -R zhangsan:zhangsan /home/zhangsan/.ssh sudo chmod 600 /home/zhangsan/.ssh/authorized_keys

然后顺手把密码登录锁死:

sudo passwd -l zhangsan

passwd -l是在/etc/shadow的密码字段前加一个!前缀,这样即使用户设置了密码也无法登录,只能走密钥认证。这个操作比“设个强密码不用”更保险,等于从认证层面直接封掉了密码通道。

如果对方是普通密码登录用户,那么在sudo passwd zhangsan这一步设置密码时,要注意PASS_MAX_DAYS这类全局密码策略。机房一般用chage -M 90指定每90天强制改密:

sudo chage -M 90 zhangsan

但说实话,如果走了密钥登录,密码过期策略对登录的影响就有限了(SSH密钥认证不经过PAM密码策略)。所以真正要管理的重点反而是密钥本身:删用户的时候,别忘了把他在其他机器上存过的公钥痕迹一并清理,这个我放到删除章节细说。

2.4 服务账号与运行账号:绝不是加个 -r 就完事

机房离不开服务账号,比如跑应用的appuser、跑数据库的mysql、跑监控的zabbix。有的新手会这么建:

sudo useradd -r -s /bin/bash appuser

-r表示创建系统用户,UID 会落在系统范围(通常小于1000),并且默认不创建家目录。看起来没问题,但有两个隐患:

一是-r创建的系统账号没有家目录,如果应用需要在$HOME下写配置文件或者日志,会报错。二是-s /bin/bash给了交互式shell,一旦应用被拿下,攻击者可以直接获得一个shell。所以正确做法应该是:

sudo useradd -r -s /usr/sbin/nologin -d /opt/appuser appuser

-d手动指定家目录为/opt/appuser,并且提前创建好,chown 给这个用户。/usr/sbin/nologin确保任何方式都无法登录shell。如果应用确实以这个用户跑起来,那也够用了。类Ubuntu系统有的没有/usr/sbin/nologin,可以用/bin/false或者/usr/sbin/nologin(实际Ubuntu也有,以系统为准),原理相同。

创建服务账号时还有一个细节:要不要把账号加入某个组?如果应用需要读/dev/gpio或/dev/video0这类硬件设备文件,通常需要把用户加入dialout、video组等。你可以把服务账号的GID主组设成业务专用的组,比如:

sudo groupadd appgrp sudo useradd -r -s /usr/sbin/nologin -g appgrp -d /opt/appuser appuser sudo chown -R appuser:appgrp /opt/appuser

这样权限边界很清晰:只有 appgrp 组能访问 app 相关的文件,别人一概不行。

3. 删除用户的规范操作:简单但绝不能贪快

3.1 userdel 默认行为和它的两个陷阱

先看命令:

# 快速删除用户(不删除家目录) sudo userdel zhangsan # 连带删除家目录和邮件池 sudo userdel -r zhangsan # 连家目录、邮件池以及用户相关文件一起删除 sudo userdel -r --remove-all-files zhangsan

userdel zhangsan默认行为是删除/etc/passwd、/etc/shadow、/etc/group里与该用户相关的条目,但不会删除他的家目录,也不会删除该用户在系统各处拥有的文件。这个特性其实有它的道理——如果某台服务器上跑着 cron 任务或者服务进程,文件删早了可能导致服务崩溃。

但机房环境的实际问题是:默认行为太保守,反而容易留坑。我见过一种情况,某同事离职后,系统里账号删了,但/home/zhangsan一直留着,里面还有.ssh/authorized_keys。后来这台服务器的SSH日志里频繁出现尝试以zhangsan登录的记录,原因就是她的公钥还留在那台机器上,而另一方面旧密码已经不再受/etc/shadow管控(账号都删了),理论上这个目录就是个没人管的后门残留。

所以我的建议是分两步走:

第一步:快速“禁”而不是“删”。

# 锁定账号,禁止一切登录 sudo usermod -L zhangsan # 设置账号立即过期 sudo usermod -e 1 zhangsan # 杀掉该用户的所有进程 sudo pkill -u zhangsan

第二步:确认没有正在运行的服务和重要数据之后,再真正删除:

# 检查进程、crontab、定时任务等是否还在使用 ps -u zhangsan crontab -l -u zhangsan # 需要root或对应权限,不同发行版可用 cat /var/spool/cron/zhangsan # 确认无关联后删除 sudo userdel -r zhangsan sudo userdel -r --remove-all-files zhangsan

为什么要分两步?因为很多生产事故不是“删错了”,而是“还在跑的时候删了”。比如某个业务是用某离职开发员的个人账号跑的,账号一删,进程还在,但文件权限全乱了。先把账号锁掉,进程还能跑,但新登录已经不可能;确认没有依赖后,再删干净,风险就小得多。

3.2 删除用户不等于万事大吉:这三处残留必须手动清

userdel -r只能清/home下的家目录和一些标准位置。我实际踩过的坑是这四处,值得单独列出来:

  • crontab残留:多数发行版里,userdel -r会顺带删除/var/spool/cron/下对应文件,但如果你以前是通过crontab单独维护的定时任务、在系统级/etc/crontab或/etc/cron.d/里写死的zhangsan定时任务,userdel可不会去动它。删完账号后这些任务还会按时触发,然后报错找不到用户或找不到命令。
  • /tmp、/var/tmp下的临时文件:userdel默认不清,这些文件之后永远没人清理,堆积多了会撑爆/分区。
  • SSH残留:/home/zhangsan/.ssh/authorized_keys如果在删除前已备份到家目录之外的地方,比如其他非标准路径,一样是隐患。
  • systemd 残留:如果该用户跑过systemd --user实例,删用户后在/var/lib/systemd/或用户Runtime目录下可能残留一堆 Runtime 文件。

实际操作的时候,我一般会先做一轮关联文件检查:

# 搜索 /home 之外属于被删用户的文件 sudo find / -path /home -prune -o -user zhangsan -print 2>/dev/null # 搜索所有可能的临时目录 sudo find /tmp /var/tmp -user zhangsan -print 2>/dev/null # 查看系统 crontab 里的引用 grep -r "zhangsan" /etc/crontab /etc/cron.d/ /var/spool/cron/ 2>/dev/null

这轮搜索可能有点慢,尤其是/全盘扫描。我习惯用find /home /var /tmp /opt /srv -user zhangsan这种范围限定,先把高频区域清干净,再全盘补扫。搜索出来后,逐个rmdir或删除,时机建议选在业务低峰期。

3.3 组和附属关系的清理:经常被忽略的一环

用户在系统里往往还牵扯一个或多个组。删除用户后,/etc/group里的成员列表会残留一个不存在的用户名。比如:

wheel:x:10:root,zhangsan

zhangsan已删,但wheel组成员列表里还有它。这倒不会造成安全问题,因为一个不存在的用户就算列在里面也没有意义,但会污染审计报表、让grep排查时产生误导。我有一次就因为这个,以为某个离职账号还有 sudo 权限,实际它早已是个空壳。

处理方式很简单:

sudo gpasswd -d zhangsan wheel

或者直接编辑/etc/group,把用户从对应行里删掉。更彻底的做法是如果该组只剩 zhangsan 一个成员且无其他用途,直接groupdel删掉这个组。

这里还有一个容易忽略的点:如果用户曾经是某个文件或目录的所有者,删除账号后这些资源会变成一个数字 UID,比如uid=1005。后续接管的人根本不知道这文件是谁的。所以删除之前,最好先迁移所有权:

# 把该用户的文件转移给 root 或指定用户 sudo find /tmp /opt -user zhangsan -exec chown root:root {} \;

这样删完之后不会留下一堆“孤儿文件”,排障和审计的时候也不会看到一堆无主 UID。

4. 批量场景与账号审计:机房的高阶玩法

4.1 批量添加用户的三种姿势

机房最大的特点就是“多”。一台台手动加,几百台机器会被活活累死。我常用的是三种方式,按场景选择:

第一种,for循环 +useradd,适合小规模几台到十几台:

for host in host01 host02 host03; do ssh root@$host "useradd -m -s /bin/bash -c '张三-系统运维' zhangsan && echo 'zhangsan' | passwd --stdin zhangsan" done

第二种,统一分发脚本。把用户创建写成 shell 脚本,放到配置管理里批量执行。比如用脚本参数化用户名和备注:

#!/bin/bash # add_user.sh user=$1 comment=$2 if id "$user" &>/dev/null; then echo "用户 $user 已存在,跳过创建" else useradd -m -s /bin/bash -c "$comment" "$user" mkdir -p /home/$user/.ssh chmod 700 /home/$user/.ssh echo "$SSH_PUBLIC_KEY" > /home/$user/.ssh/authorized_keys chown -R $user:$user /home/$user/.ssh passwd -l $user fi

第三种,用现成的配置管理工具(比如 Ansible),在 inventory 里列机器,然后统一执行。这是我最推荐的做法,因为不仅能批量加用户,还能在将来批量删用户、批量改权限,审计也更方便。当然有些环境不允许新装agent或跳板机,那就退回第一种形态,至少先解决“快”的问题。

4.2 批量删除的安全阈值设定

批量删除比批量添加危险得多,因为删错了一个账号,可能影响一大片。我给自己的硬性要求是:永远不要在没有任何“锁定确认”的情况下批量userdel。

我的批量删除流程:

  1. 先在所有机器上usermod -L锁定目标用户,同时chage -e 0强制过期。
  2. 等待一个“冷静周期”,一般至少等 24 小时或一个业务周期。期间观察监控、告警、日志,确认没有业务因为账号锁死而报错。
  3. 如果冷静期内没有任何异常,再执行真正的userdel。

非要写自动化脚本的话,我会在脚本里加上双重确认:

#!/bin/bash # del_user.sh user=$1 read -p "确认删除用户 $user ? (输入大写YES确认) " confirm if [ "$confirm" != "YES" ]; then echo "操作取消" exit 1 fi # 先锁定 usermod -L "$user" && usermod -e 1 "$user" # 再等5秒,避免手滑 sleep 5 # 最后删除 userdel -r --remove-all-files "$user" 2>/dev/null || userdel "$user"

这个脚本里read那一步就是防手滑的。删一个还好,批量删的时候服务器一多,人容易麻木,这时候确认机制就是最后的防线。

4.3 账号审计:定期给机房账号做“体检”

添加和删除用户做久了,会发现真正重要的事情不是“删干净”,而是“定期清查”。我每季度会在机房所有服务器上跑一轮账号审计,主要查这么几件事:

  • 是否存在长期未登录的账号(比如 90 天内没登录过)。
  • 是否存在 UID 0 的账号(普通用户却拥有 root UID,这是典型的后门信号)。
  • 是否存在/etc/shadow里密码字段异常或空的账号。
  • 是否存在备注信息为空、无法确认归属人的账号。
  • 是否存在/home下家目录与/etc/passwd条目不对应的孤立目录。

审计的命令往往就是几个 grep 和 find,比如:

# 查找UID 0账号 awk -F: '$3==0 {print $1}' /etc/passwd # 查找无备注的普通账号 awk -F: '$3>=1000 && $3<65534 && $5=="" {print $1}' /etc/passwd # 查找90天内未登录的账号 lastlog -b 90 | awk 'NR>1 && $2!="**" && $2!="Never" {print $1}'

把审计结果做成表格,提交给机房负责人确认:“这些账号还要吗?不要的话走删除流程。”这样一轮一轮下来,僵尸账号会越来越少,安全性也肉眼可见地提升。

审计这步还顺带解决一个管理难题:当你需要给某个账号开权限时,先看一眼审计结果,是不是有旧账号可以复用,避免账号越开越多。我这边就发生过一个典型案例:某项目借调工程师,被分配了独立的账号,但项目结束后账号没删;半年后另一个项目又用到同一人,技术负责人直接就让用旧账号,结果旧账号的权限早就过期了,卡了好半天。后来我们把所有账号统一按“项目编号+人名”备注,审计时一眼就能看出归属。

5. 常见问题与排查实录

5.1 添加用户后无法登录,排查思路是什么

这种情况我在群里帮人排查过无数次。现象是useradd回车没有任何报错,但用户 SSH 登录就是进不来。一般按这个顺序查:

首先查账号是否被锁:

sudo passwd -S zhangsan

输出会是zhangsan LK 2025-01-01 0 99999 7 -1之类,LK表示锁定,PS表示密码已设置可用。如果是NP(无密码),说明创建时没有设密码或passwd -l锁定了,需要sudo passwd -u zhangsan解锁后再设新密码。

然后查 SSH 配置里是否限制了用户:

grep -E "AllowUsers|DenyUsers|AllowGroups" /etc/ssh/sshd_config

如果全局sshd_config配了AllowUsers,但你新加的账号不在列表里,SSH 会被直接拒绝,提示Permission denied (publickey)或其他,但排除了密码问题,很容易忽略。

接着查/etc/shadow是否被 nis/ldap 等外部认证接管:

getent passwd zhangsan

如果返回结果和/etc/passwd不一致,那用户认证可能走的不是本地文件。

5.2 删除用户后目录还在,要不要手动删?

有人删完账号,发现/home/zhangsan还在,就慌了。这其实是userdel默认行为,之前说过。真正的问题不是目录在不在,而是目录里有什么。如果目录里只有普通文档,留着反而可以在将来排查历史问题时参考;但如果有.ssh或未受保护的配置文件,那就必须处理。

我的原则是:把家目录改个名字留作备份,比如/home/zhangsan_archive_日期,并移除其.ssh目录,然后归档到别的磁盘。这样做的好处是:万一以后有“这个用户的某个配置还在被某个服务引用”的情况,你还能从归档目录里捞回来。机房环境里我遇到过两次类似情况,一次是用户自己写了个 cron 脚本被另一个用户调用,一次是/home/zhangsan/.my.cnf里存着数据库密码被应用读取。如果当时直接rm -rf,恢复的代价会比“留备份”大得多。

5.3 群组删除时报错“cannot remove the primary group of user”

这是删除用户时很典型的一个报错。原因是用户被删了,但他的主组还残留着,且该组仍被标记为某个用户的 primary group(虽然那个用户实际已不存在)。解决方法很简单:

# 先确认这个组的GID是否还被引用 awk -F: '$4==GID {print $1}' /etc/passwd # 确认没有用户引用后,强制删除组 sudo groupdel appgrp

如果 groupdel 还报错,可以直接编辑/etc/group和/etc/gshadow把对应行删掉。但这是有风险的操作,动手前记得备份:

cp /etc/group /etc/group.bak cp /etc/gshadow /etc/gshadow.bak

另外,某些发行版上,如果这个组是某个用户的主组,userdel时加上-r也不一定自动删组,最终还是要手动处理。所以检查用户主组清理情况,应该被写进删除流程的 checklist 里。

5.4 如何防止“删除用户时误删其他用户”的手滑失误

机房里面误删账号的新闻并不罕见,原因往往是批量操作脚本里变量写错,或者运维用了-r参数但目标用户写错。我给自己定的规矩是:

  1. 执行删除前先id 用户名,确认目标存在且 UID 对应正确。
  2. 用userdel之前先usermod -L,锁定后退出。
  3. 批量操作时在脚本里加打印输出,每台机器执行后都记录目标 UID 和操作结果到日志文件。
  4. 设定好 alias,比如alias userdel='userdel --help'这种防御性alias,强制自己每次都用全路径或sudo /usr/sbin/userdel,想清楚再用。

这些方法看起来有点繁琐,但一旦出过事就知道,删除账号比添加账号更需要“仪式感”。

5.5 实用速查:机房添加删除用户常见问题表

现象原因解决办法
用户无法登录且无任何报错账号被锁定或过期passwd -S查看状态,usermod -U解锁,chage -E -1去除过期
SSH密钥登录无效.ssh或authorized_keys权限过大目录700,文件600,属主正确
删除用户后定时任务还在执行crontab残留检查/var/spool/cron、/etc/cron.d、/etc/crontab并清理
删用户后/home下还有文件userdel默认保留家目录先确认引用关系,再归档或删除
批量删用户中途失败个别机器上存在该用户的登录进程脚本里加pkill -u 用户名,或先锁后删
用户组删不掉仍是某用户的主组检查 UID 引用,解除后再groupdel

最后再分享一个细节

其实在机房干活,做到最后你会发现,添加和删除用户的工作量最多占10%,剩下90%是“想清楚再动手”和“动手后确认干净”。我自己吃过不少亏之后,现在每台新接手服务器都会先看一遍/etc/passwd和/etc/group的备注字段,谁是谁、什么时候加的、为什么存在,基本都能对上号。我也建议你从今天开始,每次创建用户都坚持写好备注、定好有效期、记录好密钥指纹。将来不管是删这个用户,还是做季度安全审计,都会少很多扯皮和返工。这个小习惯,比任何一条命令都值钱。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询