usermod -u 只改 /etc/passwd 里那一行:文件归属存的是数字 UID,家目录之外要手动补,已启动的进程也不会跟着变。
先分清 UID 存在哪两处
id -u alice
getent passwd alice
ls -n /srv/data/report.log
find /srv/data -nouser -print
账号表里的 UID 和文件里的数字 UID 是两套东西:权限判定用的是文件里那个数字,用户名只是运行时拿账号表换算出来的。find 的 -nouser 定义就是”没有用户对应到这个文件的数字 UID” [4]——改完 UID 后用它扫一遍,能把没被换算的残留文件捞出来。WSL 实测:改 UID 后目录外的文件仍显示 9606(没有对应名字),find -nouser 正好把它列出来。
动手前:停进程、确认新 UID 没被占用
ps -u alice -o pid,ruid,comm
awk -F: '$3==1010 {print}' /etc/passwd
cp -a /etc/passwd /etc/passwd.bak
usermod -u 1010 alice
Debian 手册的 CAVEATS 写得很直:改数字 UID 之前必须确认这个用户没有进程在跑 [2]。WSL 实测印证了这句——有进程时 usermod 直接拒绝,报 usermod: user demouser is currently used by process 430,退出码 8;把该用户的进程停掉再跑才成功。
新 UID 必须没被占用(除非加 -o),且必须非负 [1]。实测:撞号时报 usermod: UID '1000' already exists(退出码 4),-5 报 invalid user ID(退出码 3);-o 确实能强行写入重复 UID(实测两个账号同时落到 200),但文件归属会一起混淆,生产上不建议。手册还说明 usermod 不会对照 /etc/login.defs 的 UID_MIN/UID_MAX 做检查 [1],而这两个默认值是 1000 和 60000 [5]:实测 Ubuntu 里 useradd -u 200 只给一条警告照样建号,和系统账号撞号往往就是这么来的——新 UID 建议落在普通用户区间。
家目录会自动改,目录外要自己补
手册对 -u 的措辞是:用户邮箱和家目录里属于该用户的文件会被自动改,家目录之外的归属必须手动补 [1]。补的写法用 GNU 手册那条:
find /srv/data -uid 1001 -print0 | xargs -0 chown -h --from 1001 1010
-h 不改符号链接本身,--from 只处理还属于旧 UID 的文件,重复跑或扫错范围时更安全;手册原例是 find / -owner alice -print0 | xargs -0 chown -h bob,改 UID 之后 -owner 已经换算不出名字,只能按数字 UID 扫 [3]。手册同时提醒:从 find 判定到 chown 执行之间有空档,被扫目录若其他人可写会有窗口,别在 /tmp 这类共享目录上跑这条 [3]。
两个实测细节值得留意:
/ 这类特殊家目录的安全措施 [1]。我按这个条件复现了一次:家目录 owner 改成 root 后跑 usermod,里面那个文件仍是 9404。已登录的会话、cron 和目录服务要单独处理
crontab -u alice -l
systemctl restart app-worker
su - alice -c 'id -u'
已启动的进程不会回溯:实测改之前起的进程 ps 里仍是 9101,改完后新起的会话才是新 UID——这正是 usermod 宁可拒绝、要求先停进程的原因 [2]。cron 和 at 的作业手册要求手动改 [2]。如果 UID 来自 NIS/LDAP 目录服务,改本地 /etc/passwd 没有意义,要在服务端处理(这一条只核对了文档,尚未在实机验证)。改 GID 是另一回事:groupmod -g 只改组表,实测跑完文件 gid 仍是旧值,要补归属同样得走 chown。
回滚与排错速查
usermod -u 1001 alice 改回,再把文件 chown 回去;改前的 cp -a /etc/passwd 备份就是回滚依据。pkill -u alice 或重启该用户的常驻服务)再跑。-o 绕过去。参考资料
- [1] usermod(8) – Linux manual page(man7 usermod(8))
- [2] usermod(8) – passwd – Debian bookworm man page(Debian usermod(8))
- [3] chown invocation – GNU Coreutils manual(GNU chown)
- [4] find(1) – Linux manual page(find(1))
- [5] login.defs(5) – Linux manual page(login.defs(5))
文中主要命令已在 WSL Ubuntu(24.04)实测,个别条目(未装工具/安装类命令)仅核对官方文档,未实际执行。