Linux中的ut是什么意思?utmp、wtmp与utmpx文件解析

来源:草根站长作者:小团团头衔:草根站长
导读:本期聚焦于小伙伴创作的《Linux中的ut是什么意思?utmp、wtmp与utmpx文件解析》,敬请观看详情。登录到Linux服务器后执行who或last命令,屏幕上列出的用户会话从何而来?这背后依赖的是系统里的utmp与wtmp记录机制。ut是user accounting terminal的缩写雏形,相关文件以utmp记录当前登录会话,wtmp追加历史登录注销信息,现代系统多用utmpx结构提升可移植性。内核与login、sshd等程序在会话变化时写入这些文件,用户态工具再读取展示。理解它们的数据结构和读写方式,有助于排查异常登录、编写审计脚本,也能解释为什么某些容器环境里who命令输出为空。

在Linux系统里,经常听到别人说ut、utmp、wtmp这类词,尤其在排查谁登录过服务器、为什么who命令看不到用户的时候。这里的ut并不是某个独立命令,而是user accounting中关于用户会话记录的一组接口与文件的简称,核心包括utmp(记录当前登录)、wtmp(记录历史登录注销)以及后来扩展的utmpx。它们由系统C库和工具共同维护,是Linux用户审计的基础。

Linux中的ut是什么意思?utmp、wtmp与utmpx文件解析

一、utmp与wtmp到底是什么

utmp文件通常位于/var/run/utmp,它保存了系统当前所有活跃的用户会话信息,比如谁从哪个终端、哪个IP登录,登录时间是多少。系统启动时的init、用户登录时的login、远程连接的sshd,都会往这个文件里写一条记录;注销或断线时再更新或标记退出。因为只保留当前状态,所以文件一般不大。

wtmp文件一般在/var/log/wtmp,可以理解为utmp的追加日志版。每次utmp发生写入(登录或注销)时,相似内容会被追加到wtmp末尾,因此它能反映历史记录。last命令就是读取wtmp来显示曾经登录过的用户、重启时间等。这两个文件都是二进制结构,不能直接cat,需要用who、last或者专门程序解析。

1.1 utmpx的出现原因

传统utmp结构在不同Unix版本里字段长度和布局不一致,移植程序很麻烦。后来定义了utmpx(extended utmp),通过额外函数和头文件提供更统一的记录方式。Linux下utmpx往往和utmp共用底层文件,只是结构体更规范,例如增加了更长的用户名、终端名以及会话ID等字段,减少溢出风险。

在glibc中,打开utmpx会使用同样路径,程序调用getutxent、pututxline等函数操作记录。对应用开发者来说,直接依赖utmpx接口比自己解析utmp更稳妥,也能兼容不同发行版。这也是为什么很多新工具源码里看到的是utmpx而不是老utmp。

二、核心数据结构与字段含义

在Linux上,相关结构定义在头文件utmp.h或utmpx.h中。以utmpx为例,主要字段包括ut_type(记录类型,如USER_PROCESS表示普通用户登录)、ut_pid(进程号)、ut_line(终端名,如pts/0)、ut_id(终端标识)、ut_user(用户名)、ut_host(来源主机)、ut_tv(时间戳)。理解这些字段才能明白who和last显示内容的来源。

下面是一段简化版的C代码示例,展示如何读取当前utmpx记录并打印登录用户。注意其中的小于号和大于号都已经转义,符合文本代码块要求。

#include <stdio.h>
#include <utmpx.h>
#include <time.h>

int main() {
    struct utmpx *u;
    setutxent(); // 打开utmpx文件并移到开头
    while ((u = getutxent()) != NULL) {
        if (u->ut_type == USER_PROCESS) {
            printf("user: %s, line: %s, host: %sn",
                   u->ut_user, u->ut_line, u->ut_host);
        }
    }
    endutxent(); // 关闭文件
    return 0;
}

2.1 记录类型ut_type的常见值

ut_type决定了这条记录表达什么事件。EMPTY表示空记录;RUN_LVL记录系统运行级别变化;BOOT_TIME是系统启动时间;NEW_TIME和OLD_TIME与系统时钟修改有关;INIT_PROCESS、LOGIN_PROCESS代表初始化或登录进程;USER_PROCESS就是真正用户会话;DEAD_PROCESS表示进程结束。who只关心USER_PROCESS,而last会把启动、重启也列出来。

如果某个程序异常退出没有写DEAD_PROCESS,utmp里就可能残留假在线用户,导致who显示已经断线的人。这时候手动清理或重启相关服务才管用,也说明ut文件靠应用自觉维护,并非内核强制保证一致。

三、常用命令如何依赖ut文件

who命令读取utmp,列出当前登录会话;w在who基础上附加CPU和正在执行的命令;last读取wtmp,显示历史;lastb读btmp记录失败登录尝试。它们本质都是封装了C库读取函数,把二进制翻译成人能看的表格。在容器或最小系统里,如果相关文件没挂载或没被写入,这些命令就会输出空或报错。

例如下面用shell查看wtmp最后五行,需要专门工具因为不能直接看二进制:

# 显示最近五次登录历史
last -n 5
# 查看当前登录用户
who
# 检查失败登录(需要btmp存在)
lastb

3.1 为什么容器里who经常为空

很多Docker镜像为了精简不会运行login或utmp维护机制,也没有真实tty分配流程,于是/var/run/utmp要么不存在要么始终为空。此时who只能返回无结果,但这不代表没人用容器,只是没有走传统会话记录通道。若需要在容器内审计,应改用进程列表或集中式日志,而非依赖ut机制。

同理,某些无状态服务器禁用wtmp写入来减少磁盘IO,历史登录就查不到。运维时要确认文件权限和挂载情况,避免误判为安全事件。

四、编程中如何正确使用ut接口

写需要登记会话的程序时,不要直接open utmp文件写字节,而应使用C库提供的pututxline等函数。它们会加锁、处理结构对齐,并同步到wtmp(通过updwtmpx)。例如写一个简易登录记录器,应在验证用户后填充utmpx结构再提交,退出前写DEAD_PROCESS。

下面示例展示如何写一条用户登录记录:

#include <utmpx.h>
#include <string.h>

void write_login(const char *user, const char *line) {
    struct utmpx u;
    memset(&u, 0, sizeof(u));
    u.ut_type = USER_PROCESS;
    strncpy(u.ut_user, user, sizeof(u.ut_user) - 1);
    strncpy(u.ut_line, line, sizeof(u.ut_line) - 1);
    gettimeofday(&u.ut_tv, NULL);
    pututxline(&u); // 写入utmpx并追加wtmpx
}

4.1 权限与并发问题

utmp文件通常权限为644,但写入需要组或特定守护进程协助;直接让普通程序写可能失败。生产环境一般由login、systemd-logind等统一维护。自己开发工具时应避免破坏已有记录,使用库函数而非裸写,并在异常退出时尽量补写退出标记,减少脏数据。

高并发场景下多个会话同时登录,库内部通过文件锁保证不互相覆盖。理解这一点,就不会试图用shell脚本每秒echo重定向去伪造utmp,那样极易损坏二进制结构。

五、总结与排查建议

回到开头的问题,Linux中的ut是指用户记账(user accounting)里围绕utmp/wtmp的那套机制和文件,utmpx是其现代化扩展。它们不是内核强制日志,而是用户态程序协作结果。排查登录异常时,先确认文件存在与权限,再用last、who交叉验证;程序开发优先调用标准库,别手动解析二进制。

掌握这些概念,不仅能读懂系统命令输出,还能在自研审计组件时少踩坑,也明白为什么某些环境下传统命令会失效。对安全运维而言,ut文件是辅助线索,真正可靠审计仍要结合auth日志与网络层记录。

utmpwtmputmpx修改时间:2026-08-08 04:48:36

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。