尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Linux查看登录用户:who、w、last、lastlog区别与实战排查

Linux查看登录用户:who、w、last、lastlog区别与实战排查 刚接手一台服务器第一件事我会敲w有人跟我说系统有点卡我第一反应也是w排查异常登录、清理僵尸会话、写巡检脚本翻来覆去用的还是那几个命令。但有意思的是很多做了两三年的运维被问到Linux如何查看当前登录用户能脱口而出who再问w和who的区别、last和lastlog的差异就开始含糊了。这个标题看起来简单实际是一个非常典型的一题多解场景同一个需求命令不同、输出不同、适用时机也不同。今天我就把这块掰开揉碎讲清楚从最基础的who到历史登录审计再到配合排查实际故障的完整思路顺便把面试里喜欢追问的细节也一并交代了。1. 先分清who、w、users、whoami到底谁在干查看登录用户的活很多人记命令是死记硬背who看登录、w看登录、last看登录但从来不想这些命令背后的设计差异。实际上它们是四个不同的工具定位完全不同。1.1 who最朴素的现在谁在系统里who是最直接的命令不加任何参数输出长这样$ who root pts/0 2025-01-12 09:23 (192.168.1.10) zhangsan pts/1 2025-01-12 10:02 (192.168.1.23) lisi pts/2 2025-01-12 10:45 (192.168.1.34)四列信息分别是用户名、终端类型、登录时间、来源地址。这里有个细节值得注意第三列后面的括号里如果是IP说明是远程SSH登录如果是:0或者tty1这类说明是本机物理终端登录。做机房巡检或者排查内网攻击源的时候这一列就是最重要的线索。who命令还有很多参数我常用的一个是who -u会多显示一个空闲时间和进程ID。空闲时间这一列在排查谁挂在服务器上不动的时候很实用后面讲实战排查我会细说。1.2 w登录名单之外它连正在执行什么命令都给你列出来你可能要问了who已经能看登录用户了为什么还要w这就是典型的够用和好用的区别。w的输出比who丰富得多$ w 10:56:32 up 2:14, 3 users, load average: 0.08, 0.03, 0.05 USER TTY FROM LOGIN IDLE JCPU PCPU WHAT root pts/0 192.168.1.10 09:23 1:33 0.12s 0.02s vim /etc/nginx/nginx.conf zhangsan pts/1 192.168.1.23 10:02 4:25 0.05s 0.05s -bash lisi pts/2 192.168.1.34 10:45 0.00s 0.03s 0.02s top第一行是系统整体状态当前时间、系统运行时长、用户总数、负载均值。这一行在排查负载问题时可以直接当开胃菜。然后是每个登录用户的详情IDLE用户空闲了多久长时间高数值说明这个会话基本挂死了JCPU该终端所有进程累计消耗的CPU时间PCPU当前前台进程消耗的CPU时间WHAT用户当前正在执行的命令w和who的关系我习惯这么理解who是点名册w是点名册加实时监控。如果你只有时间记一个命令记w它覆盖了who的全部功能还多得多。1.3 users简洁到可以写进脚本如果说who是点名册那users就是签到单——它只输出用户名一行搞定$ users root zhangsan lisi它的价值主要体现在脚本里。比如我要写一个巡检脚本判断是否有除root之外的用户在线直接解析users的输出比解析who简单得多#!/bin/bash # 检查是否有非root用户在线 online_users$(users) if echo $online_users | grep -qv root; then echo 警告存在非root用户在线$online_users fi注意users输出中的用户名可能有重复比如同一个用户开了两个终端。如果需要去重可以用users | tr \n | sort -u。1.4 whoami它其实不回答当前有哪些用户whoami严格来说不在查看登录用户的范畴里但我发现新手经常把它和who搞混——who是看系统里有谁whoami是看我是谁。$ whoami root这个命令的真实逻辑是读取当前进程的UID然后映射用户名。它有个很隐蔽的坑如果你先su - zhangsan切换了用户再在同一个Shell里执行whoami输出的是zhangsan而不是root。但如果你用sudo -u zhangsan执行结果会受sudo配置影响。所以在排障的时候如果发现执行命令的人和登录的人对不上多半是发生了用户切换。结合后面要讲的last命令就能拼出完整的操作轨迹。2. 查看登录用户的底层档案utmp、wtmp、btmp 三个文件光会敲命令不算真懂你得知道这些命令的数据从哪来。Linux 把登录信息存在三个二进制文件里绝大多数查登录的命令都是在读它们文件路径记录内容谁来写utmp/var/run/utmp当前在线会话who、w、users读取它wtmp/var/log/wtmp历史登录/登出记录last读取它btmp/var/log/btmp失败登录记录lastb读取它utmp里的记录是动态的用户登录时写入、登出时删除所以它永远只反映此刻谁在线。wtmp是追加写入只增不减记录每一次完整的登录和登出会话。这也是为什么重启服务器后last依然能看到过去的记录——它读的是磁盘里的wtmp不是内存。btmp是个容易被忽略的存在但它恰恰是排查暴力破解的第一手资料。每次SSH密码输错Linux都会往btmp里写一条失败记录用lastb可以查看$ sudo lastb root ssh:notty 118.31.xx.xx Tue Jan 14 03:22 - 03:22 (00:00) admin ssh:notty 118.31.xx.xx Tue Jan 14 03:22 - 03:22 (00:00)你不难发现lastb输出的头几行经常是乱糟糟的一堆陌生IP后面跟的全是常见用户名这是典型的自动化爆破特征。所以我的习惯是每天瞄一眼lastb | head -20比看什么安全设备告警都来得直接。还有个文件容易被遗忘/var/run/utmp在系统重启后会被清空重建这也是为什么who只能看到本次开机以来的在线用户——重启前的登录会话全部断线了自然就不算当前登录。3. 翻开历史账本last 和 lastlog 的正确用法在线用户只是一瞬间的状态排查问题的时候你往往更关心谁在什么时候登录过、这个账号有没有被使用过。3.1 last完整的登录/登出流水账last读的是wtmp输出每次会话的记录$ last root pts/0 192.168.1.10 Mon Jan 13 09:23 still logged in zhangsan pts/1 192.168.1.23 Mon Jan 13 10:02 still logged in lisi pts/2 192.168.1.34 Mon Jan 13 10:45 still logged in root pts/0 192.168.1.10 Mon Jan 12 09:23 - 18:30 (09:07) reboot system boot 2.6.32-642.el6 Mon Jan 12 08:00 still running注意几类特殊输出still logged in这次会话还没登出就是当前在线reboot system boot系统启动记录wtmp里会写所以last能看出系统何时重启过- 18:30表示登出时间括号里是该会话的总时长last支持按用户名过滤比如只看 root 的登录历史$ last root也可以看某个终端的历史$ last pts/0这个命令在审计场景特别有用。举个例子有次同事说某个配置文件被改了但都否认是自己改的我用last拉出最近两天所有登录过这台机器的人再配合history时间戳一对比几分钟就定位到了。3.2 lastlog每个账号的最后一次登录登记表lastlog读的是/var/log/lastlog它会列出系统里所有有登录记录的账号其实是所有UID达到阈值的用户输出每个账号最后一次登录的时间和来源$ lastlog Username Port From Latest root pts/0 192.168.1.10 Mon Jan 13 09:23:28 0800 2025 daemon **Never logged in** bin **Never logged in** zhangsan pts/1 192.168.1.23 Mon Jan 13 10:02:11 0800 2025注意last和lastlog的区别last看每一次会话是流水账lastlog看每个账号的最后一次是一张汇总表lastlog最大的价值在于发现异常存活的账号。比如一个系统里有一百个账号看着都正常但跑一遍lastlog发现其中二十个显示**Never logged in**而这些账号偏偏能SSH登录这就要警惕了——正常没人用的账号通常会被锁掉。3.3 登录记录文件会无限增长吗会所以要学会管理wtmp和btmp是追加写入的二进制文件日子久了体积会膨胀。尤其btmp如果服务器常年被暴力扫描可能几个月就长到几个GB。我在生产环境见过 8GB 的btmplastb一执行直接卡住。常规做法是用 logrotate 管理这两个文件。系统一般自带配置在/etc/logrotate.d/下会有对应规则但要确认一下实际生效情况。我自己维护的服务器会单独加上按周轮转、保留4周的策略/var/log/btmp { weekly rotate 4 compress missingok }还有个小技巧日志轮转之后lastb默认只读当前的btmp要看上一周的得用lastb -f /var/log/btmp.1.gz配合zcat来处理这个到用的时候再查就行。4. 实战排查从有用户在线到定位异常会话的完整链路命令都认识了接下来聊聊真正的工作场景。这里我挑三个最常见的诉求展开判断卡顿是否与登录用户有关、找出长时间不动的僵尸会话、识别可疑的登录来源。4.1 系统变卡先用 w 看负载和现场命令服务器突然变卡登录上去第一步我会敲$ w 11:30:15 up 30 days, 5:02, 5 users, load average: 15.08, 12.03, 9.05 USER TTY FROM LOGIN IDLE JCPU PCPU WHAT root pts/0 192.168.1.10 09:23 0.00s 0.12s 0.02s w zhangsan pts/1 192.168.1.23 10:02 1:02 12.5s 11.3s python3 /tmp/check.py lisi pts/2 192.168.1.34 10:45 0.05s 0.03s 0.02s top重点看两个地方load average和WHAT列。如果负载很高而某个用户的WHAT列显示一个你不知道的进程持续在跑十有八九问题就在这个会话上。上面这个例子zhangsan在跑/tmp/check.pyCPU时间累计了 12.5 秒继续跟踪就应该顺着流程去看这个进程到底在干什么$ ps -ef | grep check.py $ ls -l /proc/pid/cwd/proc/pid/cwd可以显示进程的工作目录写脚本的服务器上这个技巧几乎每天都要用。4.2 空会话和僵尸终端IDLE 高到离谱的会话怎么清理w输出里的IDLE列超过几个小时甚至几天的会话基本可以断定是无用的遗留会话。比如某天你看到$ w USER TTY FROM LOGIN IDLE JCPU PCPU WHAT olduser pts/5 10.0.0.55 2025-01-05 14:20 22:15m 0.02s 0.01s -bash22:15m表示空闲了22小时15分钟这种会话占着终端资源虽然不会直接拖垮系统但如果批量存在也会占用大量pts设备号导致新连接分配不到终端。处理僵尸会话的步骤我一般这么走先确认该用户的会话数who -u看第二列终端号确认没有关键任务在跑ps -ef | grep pts/5排除掉还在跑的进程杀掉会话对应的进程或者直接踢掉pkill -9 -t pts/5这个操作不是随手就能做的。生产服务器上一个挂着vim没保存的会话被强杀数据就丢了。所以我给自己定了个规矩踢会话之前至少ps -t pts/5看一眼有没有正在编辑的进程。4.3 可疑来源IP一眼识别非内网登录运维的服务器一般只开放了内网SSH如果w或者who里出现陌生的公网IP这就要立刻警觉了。比如$ who root pts/0 192.168.1.10 2025-01-13 09:23 admin pts/3 185.220.101.4 2025-01-13 11:05内网网段是192.168.1.x突然冒出一个185.x.x.x的登录来源地明显不对就要走异常排查流程先看历史记录确认这个IP是不是第一次出现last | grep 185.220.101.4看失败记录里有没有大量尝试lastb | grep 185.220.101.4 | wc -l看这个会话的WHAT列在做什么命令立刻决定是否踢出pkill -9 -t pts/3再补充一个细节如果你发现last里某个用户的登录记录全来自陌生IP而他自己说没登录过那就要考虑账号密码泄露了第一时间passwd 用户名重置密码同时把所有在线会话踢掉然后去~/.ssh/authorized_keys里检查有没有多出来的公钥。别问我是怎么知道要查这玩意的都是教训换来的。4.4 盯着登录动态watch 命令组合拳排查不是一次性动作很多时候你需要持续观察。我最常用的组合是$ watch -n 1 who; echo ---; wwatch -n 1表示每秒钟刷新一次随时能看到有没有新会话进来、已有会话在跑什么命令。这在多人共用一台测试机、排查谁又在乱执行命令的场景里特别好使。想要记成日志的话可以加个时间戳追加到文件$ while true; do date /tmp/login_monitor.log; w /tmp/login_monitor.log; sleep 60; done这种粗糙的方案在应急场景比装监控系统快得多胜在五分钟内就能跑起来。5. 面试被追问的隐藏维度终端类型、切换用户与 仍然登录中这个标题在面试题里出现的频率挺高的但面试官一般不会只满足于背命令。基于我前面讲的内容有几个经常被追问的细节值得单独拎出来说。5.1 TTY 和 PTS 到底代表什么who输出的第二列pts/0、pts/1、tty1这些面试时经常被拿来作文章。tty1~tty6本机物理终端按下 CtrlAltF1~F6 切换的那种pts/N远程终端或伪终端SSH登录、xshell、securecrt 连接都属于这类更底层的说法是pts是 pseudo-terminal slave 的缩写它由sshd等程序动态分配所以你SSH登录一次pts的编号通常会加1。同一个用户多次SSH会占用多个不同的pts/N在who里就会有这个用户的多个登录记录。5.2 reboot 记录为什么也会出现在 last 里这是一个很能拉开差距的细节。last会输出系统启动记录是因为wtmp在系统启动时会被写入一条reboot记录。这条记录的 TTY 列显示system bootFROM 列显示内核版本。所以当你用last排查问题时可以顺便确认系统何时重启过比如$ last reboot reboot system boot 5.4.0-26-generic Mon Jan 13 08:00 still running要是想单独看所有重启记录last reboot是最快的命令没有之一。5.3 su 和 sudo 切换后的表面身份与真实身份表面上who看到的是登录用户名但如果你在会话里执行了su或者sudo后续命令的真实执行身份已经变了。这时候有几个命令可以确认我到底是以什么身份在干活$ id -u # 显示当前有效用户的UID $ whoami # 显示当前有效用户名 $ logname # 显示最初登录的用户名如果依次su了多次这个依然是最早那个logname是个冷门命令但它有个独特价值whoami会随su切换而变化logname不会。所以在面试里可以这样答whoami回答的是当前有效身份logname回答的是初始登录身份两个命令在排查提权和身份切换场景时需要配合使用。5.4 last 状态全解析from 里的 IP 和 still logged in 的判断逻辑last的输出有个很容易读错的点如果会话正常退出你会看到- 登出时间如果会话还在线你会看到still logged in。这两个状态的判断依据就是utmp里的对应记录是否已被清除。所以last和who拿到的是同一套数据只是last还能对比出历史完整链路而who只能看此刻的快照。有次一个同事问我为什么last里显示某用户 still logged in但who里看不到这个人这种情况多半是会话异常中断utmp记录残留了。处理方法是把对应终端的进程清一遍或者直接重启一下 sshd。反正记住一点who看不见了但last还说留着说明会话异常断开属于需要清理的烂尾会话。6. 实际维护中我沉淀下来的一套查登录习惯前面讲的知识点比较多最后分享一点我实际干活时的操作习惯。单独看每个命令都很简单但组合起来能覆盖绝大多数日常需求。我自己的例行巡检是这么做的SSH 上去先执行w看当前用户、负载、正在执行的命令这一步能筛出90%的表面问题然后last | head -20确认最近有没有异常的登录来源最后lastb | head -20看有没有明显的爆破试探。三条命令不到十秒一台机器的登录健康度基本心里有数。如果是排查具体某个用户的操作轨迹我会按时间线串联last 用户名定位这个用户最近几次登录的终端、IP、时间who -u 用户名确认该用户当前是否在线、在哪个终端ps -t pts/N看这个终端的进程列表尤其是还活着的命令需要时翻.bash_history对照时间戳还原操作再分享一个很多人忽略的点如果你管理的服务器较多建议把常用的查登录命令统一封装成一个脚本输出格式固定批量执行时能省大量时间。我自己写过一个简单的巡检脚本核心逻辑就是执行w、last、lastb三个命令把结果归档到固定目录每天定时跑一次。不求花哨胜在稳定省心。最后想提醒一句w命令输出的load average是整机的平均负载它并不是当前登录用户造成的两者有可能是巧合。所以看到高负载先别急着怪在线用户还要结合top、iostat这些工具往下查。这也是面试官最爱挖的坑之一一上来就说负载高肯定是因为有人在乱跑命令这种答案一看就是背出来的缺少实际排查经验支撑。把这些命令吃透不光是为了应付面试更是为了在服务器真正出问题的时候你手里有足够多的工具去定位和还原现场。我见过不少运维同行遇到有异常登录第一反应是把密码改了、把用户踢了但从来没想过先去看last完整还原一遍操作轨迹——这才是这个题目背后真正值钱的东西。
返回列表