讲师中心 微信公众号
AI工具推荐 视频效率加速

c++怎么实现类似于Linux下tail -f的实时日志流监控与解析【实战】

雨婷大大_2962

雨婷大大_2962

发布时间:2026-03-30 18:23:34

|

428人浏览过

|

来源于php中文网

原创

用 fopen + fseek 模拟 tail -f 需保持单 FILE* 打开、以 "rb" 模式操作,每次轮询先 fseek(fp, 0, SEEK_END) + ftell 获取当前大小,与上次偏移比较;若增大则从旧偏移 fread 新增字节;需用 fstat 检测 inode 变化应对 logrotate;手动缓冲解析换行,避免 fgets 截断。

c++怎么实现类似于linux下tail -f的实时日志流监控与解析【实战】

如何用 fopen + fseek 模拟 tail -f 的文件尾部追加监听

Linux 的 tail -f 本质是持续检查文件末尾是否有新字节写入,C++ 没有内置等价物,得自己轮询 + 定位。关键不是“读完就停”,而是“读到 EOF 后不退出,等新内容”。

常见错误是每次 fopen 重开文件——这会丢失文件描述符位置,且在日志轮转(logrotate)时可能跳过新文件;正确做法是保持单个 FILE* 打开,用 fseek(fp, 0, SEEK_END) 定位到当前末尾,再用 ftell 记下偏移量,下次从该位置开始读。

  • 必须用 "rb" 模式打开,避免文本模式下的换行符转换干扰字节定位
  • 每次读前先 fseek(fp, 0, SEEK_END),再 ftell 获取最新长度,和上次记录的偏移比较
  • 若新长度更大,说明有追加:用 fseek(fp, last_offset, SEEK_SET) 回到旧位置,再 fread 差值字节
  • 注意:如果日志被截断(truncate 或重写),last_offset 可能大于当前文件大小,此时需重置为 0 并 warn

遇到日志轮转(logrotate)怎么办:检测 st_ino 和 st_dev 是否变化

真实生产环境里,logrotate 会 rename 原文件、新建同名文件,导致你一直读着一个已停止写入的旧 inode。只靠文件路径判断完全失效。

必须在每次循环中调用 stat() 检查当前打开的 FILE* 对应的 inode 和设备号是否和上次一致。C++ 中可通过 fileno(fp) 获取 fd,再用 fstat() 读取元数据。

立即学习“C++免费学习笔记(深入)”;

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • 保存首次打开时的 st_ino 和 st_dev
  • 每次轮询前调用 fstat(fd, &sb),若 sb.st_ino != saved_ino || sb.st_dev != saved_dev,说明文件已被轮转
  • 此时应 fclose 当前句柄,open 新文件(路径不变),并重置 last_offset = 0
  • 不要依赖 access() 或 stat() 路径——rename 后路径存在但内容已变,inode 才是唯一标识

poll() or inotify?Linux 下更轻量的替代方案

纯轮询(比如每 100ms stat 一次)浪费 CPU,但 inotify 又要处理事件队列、线程同步,对简单日志监控有点重。折中方案是用 poll() 监听文件 fd 的可读事件——仅适用于支持 POLLIN 的文件系统(ext4/xfs 通常支持,但 NFS 不一定)。

实测发现:对普通本地日志文件,poll() 配合 O_NONBLOCK 打开,比 busy-loop 更省资源,且无需额外权限或 inotify 限额管理。

  • 用 open(path, O_RDONLY | O_NONBLOCK) 替代 fopen
  • 构造 struct pollfd,设置 .fd = fd,.events = POLLIN
  • poll() 返回 > 0 时,说明有新数据可读(不一定整行,需自行缓冲解析)
  • 注意:poll() 不保证返回时数据已落盘,仍需结合 lseek(fd, 0, SEEK_END) 校验长度,防止误触发

解析日志行时为什么不能直接用 fgets()?缓冲与换行边界问题

日志写入是流式的,一行可能分多次 write(),而 fgets() 在遇到 EOF 或换行符前会阻塞或返回不完整结果。更糟的是,如果最后一行没换行符(常见于 crash 日志末尾),fgets() 就永远卡住或丢掉它。

必须自己维护读缓冲区,按字节累积,手动查找 '\n' 边界,保留未完成行供下次拼接。

  • 分配固定大小缓冲区(如 4KB),每次 read() 或 fread() 追加到 buffer 末尾
  • 扫描 buffer 中所有 '\n',逐行提取(注意 Windows 的 "\r\n" 要统一处理)
  • 将最后一个 '\n' 后的内容移到 buffer 开头,更新长度,作为下一轮的“残留”
  • 避免用 std::string 频繁拼接——日志量大时内存抖动明显,用 std::vector<char></char> 管理更可控

真正麻烦的从来不是“怎么读到新内容”,而是“怎么确认这一行确实写完了、没被截断、也没和下一行粘连”。inode 检测、偏移校验、缓冲切分,三者缺一不可。漏掉任何一个,线上跑一周后就会开始丢日志。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

6799

2023.08.02

fclose函数的用法
fclose函数的用法

fclose是一个C语言和C++中的标准库函数,用于关闭一个已经打开的文件,是文件操作中非常重要的一个函数,用于将文件流与底层文件系统分离,释放相关的资源。更多关于fclose函数的相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

842

2023.11.30

fgets在c语言中的用法
fgets在c语言中的用法

本专题整合了c语言中fgets用法介绍,阅读专题下面的文章了解更多详细内容。

153

2025.08.27

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

4438

2023.08.10

windows查看端口占用情况
windows查看端口占用情况

Windows端口可以认为是计算机与外界通讯交流的出入口。逻辑意义上的端口一般是指TCP/IP协议中的端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等等。怎么查看windows端口占用情况呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

3319

2023.07.26

查看端口占用情况windows
查看端口占用情况windows

端口占用是指与端口关联的软件占用端口而使得其他应用程序无法使用这些端口,端口占用问题是计算机系统编程领域的一个常见问题,端口占用的根本原因可能是操作系统的一些错误,服务器也可能会出现端口占用问题。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2898

2023.07.27

windows照片无法显示
windows照片无法显示

当我们尝试打开一张图片时,可能会出现一个错误提示,提示说"Windows照片查看器无法显示此图片,因为计算机上的可用内存不足",本专题为大家提供windows照片无法显示相关的文章,帮助大家解决该问题。

1508

2023.08.01

windows查看端口被占用的情况
windows查看端口被占用的情况

windows查看端口被占用的情况的方法:1、使用Windows自带的资源监视器;2、使用命令提示符查看端口信息;3、使用任务管理器查看占用端口的进程。本专题为大家提供windows查看端口被占用的情况的相关的文章、下载、课程内容,供大家免费下载体验。

2639

2023.08.02

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

40

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn