Linux下获取用户在线时长需通过who/w命令解析登录时间或loginctl获取systemd会话时间,/proc/uptime仅反映系统运行时间;Windows无统一指标,依赖事件日志或注册表,跨平台应明确业务定义再选路径。

Linux下读取/proc/uptime只能得到系统运行时间,不是用户在线时长
很多人误以为/proc/uptime能反映某个用户的登录时长,其实它只记录内核启动以来的总运行秒数(包括空闲),和用户行为完全无关。真正需要的是登录会话的起始时间——这得从进程或登录记录里反推。
通过who或w命令解析当前登录会话的起始时间
Linux中每个终端登录都会产生一个sshd、login或gdm-session-worker等进程,其启动时间即为该会话开始时间。C++可通过popen("who -u", "r")获取带时间戳的登录信息:
user1 pts/0 2024-05-20 14:22 . 12345 00:42
其中00:42是空闲分钟数,而14:22是登录时间(需结合日期判断是否跨天)。更可靠的是用w -h输出的第3列(LOGIN@)和第4列(IDLE),但注意:图形界面登录可能不显示在who里,得查systemd-logind或loginctl。
-
who -u只显示TTY/SSH会话,不包含Wayland/X11桌面会话 - 时间字段格式依赖locale,建议用
LANG=C who -u固定格式 - 多用户同时登录时,需按用户名过滤,避免混入他人会话
调用loginctl获取systemd系统下所有用户会话的精确登录时间
现代Linux发行版(Fedora/RHEL/CentOS 7+、Ubuntu 16.04+)默认使用systemd-logind管理会话,loginctl list-sessions --no-pager输出结构清晰,配合loginctl show-session <id>可拿到TimestampMonotonic或Timestamp(ISO8601格式):
立即学习“C++免费学习笔记(深入)”;
$ loginctl show-session 3 -p Type -p State -p Timestamp Type=seat State=active Timestamp=Mon 2024-05-20 14:22:33 CST
C++中可用popen("loginctl show-session $(loginctl | grep $(whoami) | awk '{print $1}') -p Timestamp 2>/dev/null", "r")提取当前用户的最新活跃会话时间,再用std::get_time解析。注意:
-
loginctl需用户有login组权限,普通用户默认可查自身会话 - 返回空或报错
No sessions found说明用户未通过PAM登录(如直接su或cron启动) -
Timestamp是本地时间,TimestampMonotonic是纳秒级启动偏移,需配合/proc/uptime换算,但精度更高且不受系统时间跳变影响
Windows平台没有统一“用户在线时长”概念,NetSessionEnum仅返回网络会话而非本地登录
Windows不维护类似Linux的“用户累计在线”指标。API如NetSessionEnum只枚举SMB共享连接;WTSEnumerateSessions返回RDP/Console会话,但dwConnectTime字段在Win10+常为0或不可靠。实际可行路径只有:
- 读取事件日志(Event Log)中
Security频道的4624(登录)和4634(登出)事件,用Evtx解析或QueryRecentEventsAPI - 检查
HKEY_USERS\<SID>\Software\Microsoft\Windows\CurrentVersion\Authentication\LogonUI下的最后登录时间(不实时,且仅限交互式登录) - 调用
GetLastInputInfo()只能获知“上次用户输入时间”,无法区分是否处于锁屏或远程会话
跨平台代码若硬要统一逻辑,建议放弃“累计时长”,改用“最近一次登录距今秒数”作为代理指标,并明确文档说明其局限性。
真实场景里,所谓“用户在线时长”往往隐含业务定义:是会话存活时间?还是键盘鼠标活跃时间?还是服务端token有效时间?别被术语带偏——先确认需求方到底想度量什么,再决定从哪条路径取数。


















