Linux下读取/proc/uptime可获取系统开机总秒数(首浮点数),用std::ifstream配合sscanf解析,避免溢出与截断;每分钟日志需用sleep_until对齐整分钟时刻,并每次重读uptime防重启失准。

Linux 下读取 /proc/uptime 获取开机总秒数
Linux 内核通过 /proc/uptime 暴露两个空格分隔的浮点数:第一个是系统已运行的总秒数(含小数),第二个是空闲时间。C++ 里只需打开文件、读一行、sscanf 解析即可,不需要调用系统命令或依赖第三方库。
常见错误是直接用 std::ifstream 读整行后忽略小数部分,或误以为第二个值才是 uptime;也有人试图用 sysinfo(),但它返回的是 long 类型,32 位系统上约 497 天就溢出,而 /proc/uptime 始终可靠。
- 用
std::ifstream打开/proc/uptime,读取整行字符串 - 用
sscanf(line.c_str(), "%lf", &uptime_sec)提取第一个浮点数(第二个值可忽略) - 注意:该文件权限为
-r--r--r--,普通用户可读,无需 root - 不要用
std::stod或std::atof直接转整行——空格会截断,必须先切分或用sscanf
每分钟写入 log 的稳定循环怎么写
不能用 sleep(60) 硬等,否则每次执行耗时(如磁盘延迟、日志格式化)都会累积误差,1 小时后可能偏移几十秒。正确做法是计算下一次写入的绝对时间点,再用 std::this_thread::sleep_until 对齐。
使用场景是后台常驻小工具,不是一次性脚本;要求日志时间戳和实际写入时刻尽量一致,方便后续按分钟聚合分析。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 初始化时用
std::chrono::steady_clock::now()记录起始时刻 - 每次循环:算出下一个整分钟时刻(例如当前是 10:23:45.123 → 下次写入在 10:24:00.000)
- 调用
std::this_thread::sleep_until(next_minute),而非sleep_for(60s) - 写日志前重新读一次
/proc/uptime,避免睡眠期间系统重启导致数据陈旧
log 文件写入的安全与性能权衡
每分钟追加一行,看似简单,但并发写、磁盘满、权限丢失都可能让日志中断。不建议每次打开-写入-关闭,也不建议长期持有文件句柄(进程意外退出会导致文件未 flush)。
典型错误是用 std::ofstream 每次 open(..., std::ios::app) 但没检查 is_open();或者用 fopen 后忘记 fflush,断电时最后一两条丢失。
- 每次写入前用
std::ofstream f(path, std::ios::app)打开,写完立即析构(自动 close + flush) - 路径建议写死为
/var/log/uptime.log或用户家目录下的uptime.log,避免相对路径引发权限问题 - 写入内容推荐格式:
2024-05-22T10:24:00Z 123456.78(ISO 时间 + uptime 秒,用空格分隔) - 如果日志量大(比如同时写多字段),才考虑缓冲区 + 定期 flush;单行没必要
跨平台?别试了,Windows 没有 /proc/uptime
这个方案只适用于 Linux。Windows 下没有对应机制:WMI 查询 Win32_OperatingSystem.LastBootUpTime 返回的是启动时间戳,需自己算差值,且需要 COM 初始化和管理员权限才能稳定获取;macOS 用 sysctlbyname("kern.boottime"),但返回的是 struct timeval,还得转成秒。
如果你真要跨平台,别硬套一个接口——直接按系统分支写三段逻辑。但绝大多数“每分钟存 uptime”的需求,就是跑在树莓派、服务器或 Docker 容器里的 Linux 环境,强行跨平台反而增加维护成本和失败点。
真正容易被忽略的是:/proc/uptime 在容器中返回的是宿主机 uptime,不是容器启动时间。如果跑在 Docker 里又想测容器存活时长,得改用记录容器内进程启动时间(如读 /proc/1/stat 的第 22 字段)。


















