跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 如何简单实现读取一个 txt 日志文件的前十行并删掉这十行,同时不能影响这个日志文件的实时写入,这个日志文件大概 1~ 2G 左右?
未分類
26 3 月 2020

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

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

資深大佬 : frozenway 16

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

大佬有話說 (50)

  • 資深大佬 : jmc891205

    说说看为什么会有这种需求
    可能有更好的解决办法

  • 主 資深大佬 : frozenway

    @jmc891205 想逐行分析 nginx 日志,看看访客的详细信息

  • 資深大佬 : littlewing

    @frozenway 那为什么要删掉前几行?

  • 主 資深大佬 : frozenway

    @littlewing 不删掉,下次再读取前十行还是它啊

  • 資深大佬 : ic2y

    那为什么不用 fseek

  • 資深大佬 : Jooooooooo

    既然是读取分析的需求, 那分析的时候跳过前十行不就行了?

  • 資深大佬 : eason1874

    fseek + fgets 分块读取就行了,用不着动文件。

    比如一次读 100KB,如果最后一行不完整就留着,下次读取块之后加在前面就行。

  • 資深大佬 : jimmyismagic

    千万不要多线程处理文件,会乱掉的,哈哈

  • 資深大佬 : sanggao

    sed

  • 主 資深大佬 : frozenway

    @ic2y @eason1874 这个应该怎么写?
    @Jooooooooo 不是跳过那么简单

  • 主 資深大佬 : frozenway

    @sanggao sed 是 shell 命令吧?

  • 資深大佬 : leido

    tail -n +11 path_to_file > newfile
    mv newfile path_to_file

  • 主 資深大佬 : frozenway

    @leido 这个只是删除前十行吧,我还要读取前十行呢

  • 資深大佬 : vk42

    保存上次读完 10 行之后的位置,下次 fseek 不就行了,为啥要费劲删 10 行

  • 主 資深大佬 : frozenway

    “array_shift — 将数组开头的单元移出数组” ,有没有类似这样的文件出栈的功能函数?

  • 主 資深大佬 : frozenway

    @vk42 因为不想文件越来越大

  • 資深大佬 : beastk

    按天生成日志不就得了

  • 資深大佬 : ipwx

    @frozenway 首先必须说明,我没听说过操作系统会提供“删掉文件前多少字节”这种功能。所以大概率主你的字面需求是完成不了的。

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

    1 、固定文件大小,把整个文件当做一个 circular buffer 用(记满了从尾巴跳到开头再开始写,直接覆盖老的内容)。然后用一个额外的小文件记录你有效的起始指针和尾指针的文职。
    2 、不要用行这么大的粒度,粗略一点。比如每 500KB 换一个文件写。文件太多了就把老的文件删掉一个。
    3 、上数据库。
    4 、模仿数据库,自己用 B+ 树管理每一行的精确位置,自己管理文件被废弃的部分的回收再利用,自己管理文件存储碎片。也就是自己创造一种“数据库”。

  • 資深大佬 : cholerae

    日志库不都有设置单个文件大小和 rotate 文件的功能吗?

  • 資深大佬 : cholerae

    说回你的这个需求本身,有个系统调用是 fallocate,fallocate 支持一个参数叫 FALLOC_FL_PUNCH_HOLE,这个东西支持把指定 fd 的偏移区间的块给释放掉,这样就不占空间了。不过不会改文件的元信息,所以你去 ls 还是看到原本的大小,需要你自己维护一个偏移量。

  • 資深大佬 : miao1007

    logstash

  • 資深大佬 : GrayXu

    @frozenway “不想文件越来越大”这个需求显然是独立的。再额外做日志切割就好了……

  • 資深大佬 : love

    你就不能下次从第 20 行开始读起?每读 10 行就复制一整个上 G 的文件,这个效率是嫌服务器负载太低了吗

  • 資深大佬 : winglight2016

    虽然我没用过 php,但是日志分析这么基础的需求,不用再自己造轮子了吧?

  • 資深大佬 : julyclyde

    这是一个很典型的
    自行分析了需求然后给出错误解方案
    然后上网问怎么实现这个错误方案
    的案例

  • 資深大佬 : myqoo

    正好写过完全相同的案例~ 每隔一段时间执行就可以:

    logtime=$(date “+%Y-%m-%d-%H-%M-%S”)

    mv 日志路径 备份目录 /$logtime.log

    touch 日志路径

    nginx -s reopen

  • 資深大佬 : hstdt

    要是我来做,我可能会使用 sqlite

  • 資深大佬 : ETiV

    mkfifo ?

  • 資深大佬 : asilin

    很简单,用 sed -i -c 参数就可以完成,具体参见下面的链接:
    https://stackoverflow.com/questions/36930913/extra-null-characters-when-sed-edit-the-file-in-place-which-under-wirting

  • 資深大佬 : banxiaobu

    我更感兴趣的是这个是什么样的背景需要这么玩

  • 資深大佬 : burringcat

    直接用 shell 就行,不要再用 php 把 shell 包起来!!!

  • 資深大佬 : tlday

    我没有搞懂为什么要删掉,假如不需要删掉
    你可以试试这个:
    head -10 access.log #读取前 10 行
    head -20 access.log | tail -10 #读取 10-20 行
    head -30 access.log | tail -10 #读取 20-30 行
    ……依此类推

    可能还有这个:
    mkfifo log_seeker
    cat access.log > log_seeker &
    exec 3< log_seeker
    head -10 log_seeker #读取前 10 个
    head -10 log_seeker #读取下 10 个
    head -10 log_seeker #读取下 10 个
    …依此类推
    完了使用
    fg # 调出上面的 cat 进程 Ctrl+C 掉
    exec 3<&- # 关掉用来保持 cat 进程的 reader 进程,参考: https://unix.stackexchange.com/questions/366219/prevent-automatic-eofs-to-a-named-pipe-and-send-an-eof-when-i-want-it

  • 資深大佬 : muzuiget

    #25 果然是 X/Y 问题。

  • 資深大佬 : tlday

    我上面的例子,如果你不手动杀掉 cat 进程,或者关掉用来保持 cat 进程的 reader 进程,就可以“无论间隔多久,下一次程序运行也是读取接下来的十行”

  • 資深大佬 : tlday

    不想文件越来越大是典型的 log rotation 的应用场景,你这是两个需求。

  • 資深大佬 : msg7086

    你 sed 途中遇上 nginx 写入的话你就等着丢数据吧。
    (丢的概率有多大呢?这么说吧,流量高的站百分百丢数据。)

    好好的 logrotate 不用,偏要走邪道……

  • 資深大佬 : mostkia

    php 相关的程序日志,可以存到 SQLite 里面啊,一般 Nginx+PHP 的环境都带的。操作真的方便一个数量级,虽然都带文件锁,但你写 TXT 绝对好不到哪里去。以后导入导出也方便。如果你是要存 nginx 的日志的话,直接每天分割日志不就行了,然后可以视文件大小或者日期进行旧文件管理。

  • 資深大佬 : ClarkAbe

    删这 10 行用乐观锁,其他的保持原样读写

  • 資深大佬 : lepig

    这好像 PHP 面试的时候 经常会问 怎么使用 PHP 处理大日志文件 擦

  • 資深大佬 : dreamage

    es 不香么

  • 資深大佬 : changePro

    典型的错误案例,怎么解决都是错。

  • 資深大佬 : vk42

    @frozenway 控制 log 文件大小不是 logrotate 的事,为啥要自己瞎搞? OS 的文件设计模型就是不适合从头部和中间删内容,不然 ftruncate 为啥不直接提供接口。如果你 log 文件本身上 G,你的这个解决方案真的是嫌 server 闲得没事干……

  • 資深大佬 : hallDrawnel

    典型的 XY Problem 例子,还好第一个回帖的就把方向带回来了。

  • 資深大佬 : tozp

    你实现了也不可取,实时操作 IO 占用太多资源,不如全放内存,周期性再写入文件。

  • 資深大佬 : xuanbg

    日志的打开方式只有两种。一种是结构化后进行各种指标统计,你可以想象为一个监控大屏。另一种是用一个或若干个关键词搜索出相关的日志,你可以想象为系统出了问题通过日志排查错误。

    主你这种日志的打开方式说不好听点纯粹是没事干……

  • 資深大佬 : sparkmlib

    logstash + ES + kinba

  • 資深大佬 : roychan

    @cholerae 可以用 FALLOC_FL_COLLAPSE_RANGE,这样文件中间就没有洞了。

  • 資深大佬 : CoderGeek

    可以将文件分段存储 1 天一个分为大小或后缀的多个文件 nginx 也可以设置 再用 shell 直接读取都可以的 你这个删除在写入的思路不太合适

  • 資深大佬 : fensou

    @sparkmlib logstash 换 filebeat+nginx module,连 dash 都自带了

  • 資深大佬 : fensou

    graylog 其实更方便

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具