如何简单实现读取一个 txt 日志文件的前十行并删掉这十行,同时不能影响这个日志文件的实时写入,这个日志文件大概 1~ 2G 左右?

2020 年 5 月 4 日
 frozenway

用 fread 先读出来,去掉再 fwrire 覆盖原来的,会不会造成期间写入文件的日志信息?

8527 次点击
所在节点    PHP
50 条回复
jmc891205
2020 年 5 月 4 日
说说看为什么会有这种需求
可能有更好的解决办法
frozenway
2020 年 5 月 4 日
@jmc891205 想逐行分析 nginx 日志,看看访客的详细信息
littlewing
2020 年 5 月 4 日
@frozenway 那为什么要删掉前几行?
frozenway
2020 年 5 月 4 日
@littlewing 不删掉,下次再读取前十行还是它啊
ic2y
2020 年 5 月 4 日
那为什么不用 fseek
Jooooooooo
2020 年 5 月 4 日
既然是读取分析的需求, 那分析的时候跳过前十行不就行了?
eason1874
2020 年 5 月 4 日
fseek + fgets 分块读取就行了,用不着动文件。

比如一次读 100KB,如果最后一行不完整就留着,下次读取块之后加在前面就行。
jimmyismagic
2020 年 5 月 4 日
千万不要多线程处理文件,会乱掉的,哈哈
sanggao
2020 年 5 月 4 日
sed
frozenway
2020 年 5 月 4 日
@ic2y @eason1874 这个应该怎么写?
@Jooooooooo 不是跳过那么简单
frozenway
2020 年 5 月 4 日
@sanggao sed 是 shell 命令吧?
leido
2020 年 5 月 4 日
tail -n +11 path_to_file > newfile
mv newfile path_to_file
frozenway
2020 年 5 月 4 日
@leido 这个只是删除前十行吧,我还要读取前十行呢
vk42
2020 年 5 月 4 日
保存上次读完 10 行之后的位置,下次 fseek 不就行了,为啥要费劲删 10 行
frozenway
2020 年 5 月 4 日
“array_shift — 将数组开头的单元移出数组” ,有没有类似这样的文件出栈的功能函数?
frozenway
2020 年 5 月 4 日
@vk42 因为不想文件越来越大
beastk
2020 年 5 月 4 日
按天生成日志不就得了
ipwx
2020 年 5 月 4 日
@frozenway 首先必须说明,我没听说过操作系统会提供“删掉文件前多少字节”这种功能。所以大概率楼主你的字面需求是完成不了的。

但是解决方案有很多。比如:

1 、固定文件大小,把整个文件当做一个 circular buffer 用(记满了从尾巴跳到开头再开始写,直接覆盖老的内容)。然后用一个额外的小文件记录你有效的起始指针和尾指针的文职。
2 、不要用行这么大的粒度,粗略一点。比如每 500KB 换一个文件写。文件太多了就把老的文件删掉一个。
3 、上数据库。
4 、模仿数据库,自己用 B+ 树管理每一行的精确位置,自己管理文件被废弃的部分的回收再利用,自己管理文件存储碎片。也就是自己创造一种“数据库”。
6ufq0VLZn0DDkL80
2020 年 5 月 4 日
日志库不都有设置单个文件大小和 rotate 文件的功能吗?
6ufq0VLZn0DDkL80
2020 年 5 月 4 日
说回你的这个需求本身,有个系统调用是 fallocate,fallocate 支持一个参数叫 FALLOC_FL_PUNCH_HOLE,这个东西支持把指定 fd 的偏移区间的块给释放掉,这样就不占空间了。不过不会改文件的元信息,所以你去 ls 还是看到原本的大小,需要你自己维护一个偏移量。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/668435

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX