ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux用户管理全解析:从登录注销到用户组权限实践

Linux用户管理全解析:从登录注销到用户组权限实践 刚接触Linux那会儿我干过一件傻事拿到一台云服务器第一件事就是用root登录之后所有操作都怼在root下完成。结果有次改坏了配置文件想查是谁干的都查不出来因为所有人都是root。后来乖乖建了普通用户用sudo提权处理日常操作才真正体会到Linux用户体系的设计意图——它不只是给你一个登录账号而是整套权限审计和隔离机制的地基。这篇文章就顺着登录注销→用户管理→用户组这条线把这块内容完整捋一遍。不管你是刚装好虚拟机准备入门还是已经在用Linux但一直对用户权限、切换用户稀里糊涂这篇都能给你一个能直接照着敲的完整脉络。1. 登录与注销从拿到终端到会话销毁的完整链路1.1 登录的本质身份认证与会话建立先想清楚一个问题登录到底是干什么表面上看是输入用户名密码实际上是两件事第一系统验证你的身份确认你确实是你声称的那个人第二认证通过后系统为你建立一个会话session在这个会话里你会拿到一个shell之后的命令都在这个shell里跑。本地登录的链路大概是这样的系统启动后systemd会拉起getty程序监听终端tty1到tty6你在界面里输入用户名后getty调用login程序做身份校验校验通过后login再去启动你账号指定的shell默认通常是/bin/bash。整个链路可以用一句话概括内核只负责管理进程用户的身份由登录认证程序把关。远程登录SSH也是一样的逻辑只是把身份认证环节换成了sshd服务来做。你通过ssh登录一台服务器本质上是客户端和sshd建立一个加密通道然后sshd帮你启动一个shell会话。搞清楚这个链路有什么用用处大了。你会发现登录后拿到的是一个进程shell这个进程归属于你登录的那个用户。你在终端里执行的所有命令都是这个shell的子进程这些进程的UID用户ID就是你登录的那个用户的UID。后面会讲到文件权限判断——一个进程能否访问某个文件看的就是进程的UID和GID与文件属主、属组是否匹配。这一切的源头就在登录这一步。1.2 注销命令家族exit、logout、CtrlD到底什么区别学会登录之后第一件该学会的事是干净地退出。很多新手刚用Linux时终端窗口一关了事这其实不太健康。在Linux里退出一个登录会话有三种常用方式# 方式一在shell里直接输入 exit # 方式二bash登录shell专用 logout # 方式三快捷键 CtrlD这三种方式有细微差别logout是bash内建命令只在登录shelllogin shell里有效如果你在普通子shell里敲logout会报错——这一点在用su切换用户时特别容易踩坑。exit则是通用的退出命令不管在登录shell还是子shell里都能用。CtrlD本质上是向终端发送一个EOF文件结束符shell收到EOF后也会退出当前会话。实际使用中的建议是一般场景下敲exit就够了严谨程度足够且不容易出问题。如果是在su切换过去的用户里要退回原用户也要用exit而不是logout因为su创建的不一定是登录shell。还有一个经常被忽略的问题**关掉终端窗口和exit有区别吗**有。exit是正常退出shell会给父进程一个退出状态码相关会话资源会被正常回收直接关终端窗口本质上是终端模拟器程序被关闭发送SIGHUP信号给shellshell再把这个信号转发给它的子进程后台任务可能因此被中断。所以如果你在跑一些后台任务比如nohup或者tmux里一定要搞清楚会话的归属关系别随便关窗口。1.3 一个实操细节为什么Ubuntu默认不允许直接用root登录这块内容在很多教程里被简单带过但它是理解登录机制很好的切入点。Ubuntu安装时创建的账号是一个普通用户但可以用sudo提权成root执行命令。系统默认没有给root设置密码所以你不能直接在登录界面输入root然后登录。这个设计不是偷懒而是有安全考虑root权限太大日常操作全用root身份跑一旦敲错命令比如rm -rf老毛病毁掉的是整个系统而且无法追溯。普通用户sudo的方案把日常不越权操作作为默认状态要用管理员权限时单独加sudo前缀系统会记录sudo的执行日志出了问题更容易追溯。理解了这一点你就明白为什么很多课程里老师会建议日常别用root需要特权用sudo。登录和注销表面上只是两个命令背后是整个Linux权限模型的入口。入口关把好了后面用户管理、权限判断这些内容才有意义。2. 用户管理全流程从useradd到userdel的完整命令链2.1 添加用户useradd的参数远比想象中重要新建用户的基本命令是useradd但新手最容易犯的错就是裸敲一句useradd username接着就开始困惑为什么新用户连ls都用不了。这是因为useradd的默认行为在不同发行版上不一样。以Ubuntu 20.04为例裸敲useradd会创建一个用户但不创建家目录不给设置shell用户也没有密码。这就形成了一个半成品账号。我推荐的实际操作是用一组明确的参数而不是依赖发行版默认值# 创建一个用户带家目录指定bash为登录shell并加入wheel组CentOS系 sudo useradd -m -s /bin/bash -G wheel zhangsan # 然后马上给该用户设置密码 sudo passwd zhangsan各参数的含义参数作用备注-m创建家目录/home/用户名不加这个登录后无家目录很多程序会出问题-s指定登录shell常用/bin/bash不指定的话可能被设为/bin/sh或nologin-G指定附加组如sudo组、docker组等用于授予附加权限-d指定家目录路径默认是/home/用户名可改为自定义路径-u指定UID一般不用手动指定系统自动分配-e指定账号过期日期格式YYYY-MM-DD常用于临时账号创建用户的瞬间系统其实做了几件看不见的事在/etc/passwd加一行记录、在/etc/shadow加一行密码占位符、可能创建家目录、从/etc/skel目录拷贝默认配置文件.bashrc、.profile这些。这也是为什么会有新用户的家目录里自带几个隐藏文件的原因——/etc/skel就是新用户家目录的模板。2.2 查询用户信息id、whoami、who、w、last各司其职查询用户信息是运维基本功。我爱用的命令是id它一次性把用户的UID用户ID、GID主组ID和groups附加组列表全列出来$ id zhangsan uid1001(zhangsan) gid1001(zhangsan) groups1001(zhangsan),27(sudo)这条命令的输出很关键gid是用户的主组ID主组也叫初始组groups后面跟的是附加组列表。主组和附加组的区别后面会细讲这里先记住一个判断方法id命令输出的第一个组是主组其余是附加组。常用的查询命令还有这些命令作用使用场景whoami显示当前用户名判断当前身份who显示当前登录到系统的用户查看谁在线w显示登录用户和正在执行的命令比who信息更丰富能看到负载last显示登录记录查看历史登录排错时好用finger显示用户详细信息需单独安装适合查看用户备注信息我排查问题时的习惯是先who看有哪些人登录再w看每个人在跑什么然后last确认是不是有异常登录。这一套下来大多数登录相关的问题都能定位个七七八八。尤其last配合/var/log/auth.logUbuntu系或/var/log/secureCentOS系是排查异常登录的利器。2.3 修改用户信息与锁定账号usermod的正确用法用户创建后想调整参数用usermod。它的参数和useradd高度重合但语义是修改已有用户# 把zhangsan的登录shell改成zsh sudo usermod -s /usr/bin/zsh zhangsan # 把zhangsan加入docker组注意这是覆盖式如果不加-a会清掉之前的附加组 sudo usermod -aG docker zhangsan # 锁定账号禁止登录 sudo usermod -L zhangsan # 解锁账号 sudo usermod -U zhangsan这里有个至关重要的坑usermod -G和-aG的区别。-G直接指定附加组列表如果你写sudo usermod -G docker zhangsan那zhangsan的附加组会被完全重置成只有docker之前在sudo组里的权限就没了。-aG是在现有附加组基础上追加保留原有组。所以我个人习惯是只要不是刻意重置一律用-aG。账号锁定和解锁这个功能在日常运维里很实用。员工离职、账号暂时不用不需要删用户直接用usermod -L锁掉就行。锁定的本质是在/etc/shadow里密码字段前加了个!标记让密码无法匹配从而无法登录。解锁就是去掉这个标记。2.4 删除用户的最后一步userdel该不该加-r删除用户的命令是userdel最简单的删除操作是# 仅删除用户保留家目录 sudo userdel zhangsan # 连同家目录和邮件池一起删除 sudo userdel -r zhangsan很多人纠结加不加-r。我的建议是删除测试账号、一次性账号时加-r删除有数据价值的账号时先备份家目录不加-r。-r会把/home/zhangsan整个删掉如果里面有用户自己存的脚本、配置、数据就一起没了。删错了再想找回只能靠备份没有后悔药。还有一个容易忽略的点userdel只删除用户本身不自动删除该用户作为属主遗留的文件。比如zhangsan之前在/tmp下建了个文件删除用户后这个文件还在只是在ls -l里属主显示成数字UID。这时候需要用find排查残留文件# 查找系统中所有属于已删除UID(1001)的文件 sudo find / -uid 1001 2/dev/null这也是删除用户这件事的完整形态删除用户只是开始清理残留数据才算收尾。要是图省事不检查这些孤儿文件可能成为权限混乱的源头。3. 切换用户的正确姿势su、sudo与直接登录的适用边界3.1 su和su -的区别环境变量这个隐形杀手切换用户最基础的命令是su但新手经常被它坑到。来看一个典型场景# 场景当前是普通用户想切换到root su root # 输入root密码后提示符变成了#但pwd一看还停留在原目录 # 对比加一个短横线 su - root # 切换后不仅用户变成root工作目录也变成了/rootPATH等环境变量也变成了root的环境su和su -全拼是su -l或su --login的本质区别在于su不带短横线只切换用户身份不加载目标用户的登录环境su -会模拟一次完整的登录过程会读取目标用户的/etc/profile、~/.bash_profile等环境配置文件然后切到目标用户的家目录。这个区别直接影响你切换后能否正常执行某些命令。最典型的例子是在CentOS上普通用户的PATH可能不包含/sbin如果你用su不带-切到root然后敲ip addr可能会报command not found因为当前shell的PATH里没包含/sbin。用su - root就不会有这个问题。所以我的经验就一句话切换用户时除非有明确理由否则一律用su - 用户名。宁可环境加载慢一秒也比命令找不到、变量丢失这种莫名其妙的问题省心。3.2 为什么推荐sudo而不是su直接切root很多教程建议日常操作用sudo而不是su切到root原因有三第一sudo不需要知道目标用户的密码。su切root要输root的密码这等于大家都要知道root密码密码外泄风险大。sudo只要当前用户自己的密码甚至可以通过配置实现免密。root密码可以设置得非常复杂且无人知晓。第二sudo有细粒度的授权管理。通过/etc/sudoers文件你可以指定哪些用户能以root身份运行哪些命令。比如给运维组的用户只授权systemctl和journalctl相关命令给DBA授权mysql相关命令不需要把所有root权限都交出去。第三sudo有日志审计。每次sudo执行都会被记录到/var/log/auth.logUbuntu或/var/log/secureCentOS。出了事故能查谁在什么时间用什么权限执行了什么命令这是su做不到的。具体操作上最常用的几条# 以root身份执行单条命令 sudo ls /root # 以root身份打开一个shell相当于切到root sudo -i # 或 sudo su - # 以其他用户身份执行命令 sudo -u zhangsan whoami3.3 配置sudo免密与自定义visudo到底怎么用/etc/sudoers这个文件直接明文编辑有语法风险改错了可能整个sudo都用不了。所以系统提供visudo命令来编辑它——visudo在保存时会做语法检查语法不对会拒绝保存这能防止你把自己锁在门外。常见配置这样写# 允许wheel组所有用户使用sudoCentOS默认配置 %wheel ALL(ALL) ALL # 允许zhangsan免密执行所有sudo命令 zhangsan ALL(ALL) NOPASSWD: ALL # 允许lisi只免密执行systemctl命令 lisi ALL(ALL) NOPASSWD: /usr/bin/systemctl一行配置由四部分组成用户或组、主机列表ALL表示本机所有主机名匹配、可切换的身份、(ALL)表示任意身份、最后是要执行的命令或ALL。这里有个常见的坑如果你改坏了sudoerssudo和su都暂时没法提权怎么办一个稳妥的恢复方法是如果有物理访问权限或云厂商的VNC控制台可以单用户模式rescue mode启动挂载根文件系统后手动修正sudoers如果是虚拟机且有快照直接回滚快照最省事。所以编辑sudoers前我的建议是先备份一份/etc/sudoers到/tmp出问题时能快速恢复。3.4 Ubuntu/root密码未设置的坑为什么su root输入任何密码都失败Ubuntu默认root没有密码你在普通用户下执行su root系统会提示输入密码——但你根本不知道密码是什么输什么都进不去。正确的解法有两种方法一给root设置密码sudo passwd root # 连续输入两次新密码之后就能su root了方法二不加root密码用sudo的方式拿root shellsudo -i第一种方法适合你是单机使用、确实需要root直接登录的场景第二种方法更适合服务器环境root密码保持未知日常用sudo提权。我个人的建议偏向第二种因为少一个root密码就少一分被暴力破解的入口。切换用户这块很多人会把它理解成用户管理的一个小操作但它是权限体系中极其关键的一环你用什么身份执行命令直接决定了命令能碰什么文件、改什么配置。su和sudo的边界清晰了很多权限类问题都会迎刃而解。4. 组的三个身份所有者、所在组和其他组的权限判定逻辑4.1 ls -l输出里第三列和第四列的秘密Linux里对文件的权限控制是围绕三个身份展开的文件所有者uuser、文件所在组ggroup、其他用户oother。执行ls -l时输出里第三列和第四列就是这个文件的归属信息$ ls -l /etc/hosts -rw-r--r-- 1 root root 221 4月 14 10:23 /etc/hosts第三列root是文件所有者属主第四列root是文件所在组属组。再看权限位-rw-r--r--其实可以拆成三段rw-所有者权限、r--所在组权限、r--其他用户权限。这三个身份的判定标准是排他的系统先看进程的UID是否等于文件属主UID等于就是所有者身份不等于再看进程的GID或附加组是否包含文件属组包含就是所在组身份两者都不满足就是其他用户。同一时刻一个进程相对于一个文件只能属于这三种身份之一不存在既属于所有者又属于组的情况。4.2 修改所有者与所在组chown和chgrp的实际用法修改文件归属用chownchange owner和chgrpchange group日常操作中经常两个一起用# 修改所属用户 sudo chown zhangsan /opt/test.txt # 同时修改所属用户和所属组用冒号分隔 sudo chown zhangsan:developers /opt/test.txt # 只修改所属组用chgrp也行 sudo chgrp developers /opt/test.txt # 递归修改目录下所有文件和子目录 sudo chown -R zhangsan:developers /opt/projectchown的递归参数-R是高频使用的尤其是把整个项目目录从root转给某个用户时不带-R只改了目录本身里面的文件还是root的后面该用户在里面操作还是会遇到权限问题。这里有一个容易被忽略的细节chown只有root能用普通用户不能把文件的属主改成别人因为如果谁都能改属主那权限模型就崩了。同理普通用户能改文件属组的前提是你必须是文件属主且要修改的目标组是你的附加组之一。4.3 主组与附加组的本质区别前面在id命令里看到两个组的概念这里展开讲。Linux用户有两个层面的组主组primary group用户创建时指定的组默认是用户名同名组。用户登录后进程的GID就是这个主组。用户创建文件时文件默认的属组就是创建者当时的主组。附加组supplementary groups通过usermod -aG授予的额外组。附加组的存在让你能访问归属于这些组的文件但创建新文件时默认属组仍然是你当前的主组不是附加组。举个例子zhangsan的主组是zhangsan附加组是docker。他创建一个文件后文件的属主是zhangsan属组是zhangsan而不是docker。如果想让新文件自动归到某个组里得去改目录的setgid位——那是更进阶的用法这里先不展开。查看用户主组和附加组的完整信息建议用id和groups两个命令对照$ id zhangsan uid1001(zhangsan) gid1001(zhangsan) groups1001(zhangsan),999(docker) $ groups zhangsan zhangsan : zhangsan docker第一行里gid1001(zhangsan)是主组groups里的other列表是附加组。第二行groups输出中第一个是主组其余是附加组。4.4 一个文件的权限判定实战为什么你在/tmp下能建文件在/home下却不行用一个具体的例子把所有者、所在组、其他组的判定串起来。假设系统里有这两个用户zhangsan主组zhangsan和lisi主组lisi。目录/tmp的权限是drwxrwxrwt属主是root、属组是root。分析lisi在其中建文件的过程lisi进程的UID1002不等于root(0)不满足所有者身份。lisi进程的GID1002(lisi)不匹配root组不满足所在组身份。落到其他用户身份权限位是rwtt是黏着位rwx里其他用户有w所以lisi可以在此目录创建文件。再看/home一般权限是drwxr-xr-x属主root、属组root。lisi想在这里创建一个文件怎么办其他用户的权限是r-x没有w直接被拒。这就是为什么普通用户在自己家目录外、在/home下无法直接创建文件——根目录和/home下的目录归root所有普通用户只有读和执行权限。把这三个身份和文件权限的关系梳理清楚80%的Permission denied就能自己找到原因了先id看自己的UID和GID再ls -l看文件的属主属组和权限位逐条对照问题出在哪一目了然。4.5 常用组管理命令groupadd、gpasswd和把用户塞进组的几种姿势组的管理命令不算多但用得频繁# 新建组 sudo groupadd developers # 把用户加入组不指定组成员文件直接改也行但推荐用命令 sudo gpasswd -a zhangsan developers # 从组里移除用户 sudo gpasswd -d zhangsan developers # 修改用户主组-g和-G别看混 sudo usermod -g developers zhangsan # 改主组 sudo usermod -G developers zhangsan # 设置附加组列表覆盖式 sudo usermod -aG developers zhangsan # 追加附加组useradd建用户时可用-G直接指定附加组这和usermod的-G是两码事但写法一致容易混淆的是usermod的-G会覆盖原附加组而useradd的-G只是新用户创建时的初始附加组不存在覆盖一说。组管理里还有一个常见的坑用户加入新组后已经登录的终端不会立即生效。因为登录时shell已经拿到了当时的附加组列表新加入的组要重新登录或者执行newgrp命令才会生效。不少运维刚把用户加到docker组里就让他执行docker命令结果报权限不足其实重新登录一下就好了。5. 几个能直接落地的用户管理建议5.1 创建用户的实用组合拳生产环境向基于前面讲的内容我在生产环境上创建用户的习惯是# 创建用户指定家目录、shell同时设置密码策略宽限 sudo useradd -m -s /bin/bash -G sudo,developers zhangsan # 设置密码生产环境建议用强密码或密钥认证 sudo passwd zhangsan针对服务器场景如果这个账号是给运维人员用的我一般还会顺手做两件事一是把SSH登录限制在ssh key方式编辑/etc/ssh/sshd_config二是把账号的登录记录和shell命令历史保持住方便以后审计。之前讲的所有者、所在组、其他组这套权限模型在管理多名运维时配合sudoers的细粒度配置能解决大部分权限越界的问题。5.2 关于root密码该不该设置的最终建议Ubuntu默认不设置root密码这个设计我越来越觉得合理。日常维护用sudo提权足够部分操作比如系统救急用sudo -i进入root shell。如果机器上只有一两个管理员保持root密码未知是很好的默认状态。如果团队人数多了建议配置集中认证如LDAP或RADIUS而不是每个人都用root密码登录。5.3 做任何用户操作前先问三个问题最后分享一个我养成的习惯。每次涉及用户操作创建、删除、加组、改权限先问自己三句话我当前是以什么身份在执行这个命令whoami看一下这个操作影响的目标用户/组是谁id和ls -l确认一下如果我执行错了有没有回滚方案备份sudoers、快照、或者文件属主记录这三个问题想清楚基本能过滤掉90%以上的低级失误。Linux不是Windows那种可视化点击的权限管理方式它的文本命令虽然看起来古老但每一步操作都可追溯、可重复、可脚本化这也是它在服务器领域屹立不倒的原因之一。把这套用户管理的思维建立起来后面再学权限、磁盘、服务管理会顺畅很多。
返回列表