Linux 下遍历大文件每一行的最佳方法,最好是命令

2015-12-05 10:46:00 +08:00
 vus520
via: http://liuzhiqiangruc.iteye.com/blog/1454797

原始需求是想监控文件增加的每一行,传给外部程序处理。

实际上的办法是定时遍历文件的每行,再传给外部程序处理。
5323 次点击
所在节点    问与答
94 条回复
looyao
2015-12-05 18:25:15 +08:00
这里可以粘帖代码么,额
//tail_demo.c

#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>

#include <sys/inotify.h>


int tail(char *path, long *pos);

int main(int argc, char *argv[])
{
int inotify_fd, watch_fd, n;
long pos;
struct inotify_event event;
void *evp;
char *path;

if (argc != 2) {
return -1;
}

path = argv[1];
pos = 0;

if (tail(path, &pos) < 0) {
return -2;
}

evp = &event;

inotify_fd = inotify_init();
watch_fd = inotify_add_watch(inotify_fd, path, IN_MODIFY | IN_DELETE_SELF | IN_MOVE_SELF);
if (watch_fd <= 0) {
fprintf(stderr, "inotify_add_watch error:%s\n", path);
return -3;
}

//这里可以使用 select, poll 轮询下 inotify_fd

while (1) {
bzero(&event, sizeof(struct inotify_event));
n = read(inotify_fd, evp, sizeof(struct inotify_event));
if (n <= 0) {
fprintf(stderr, "read error\n");
break;
}

if (event.mask & IN_MODIFY) {
tail(path, &pos);
}
}

}

int tail(char *path, long *pos)
{
FILE *handle;
char buf[1024];

handle = fopen(path, "r");
if (!handle) {
fprintf(stderr, "can't open file:%s\n", path);
return -1;
}

fseek(handle, *pos, SEEK_SET);

while (!feof(handle)) {
bzero(buf, sizeof(buf));
fgets(buf, sizeof(buf), handle);
printf("%s", buf);
*pos = ftell(handle);
}

fclose(handle);
}


编译:
gcc tail_demo.c -o tail_demo
使用:
./tail_demo 文件路径
xufang
2015-12-05 18:39:20 +08:00
牛哄哄喷我的小学生呢,不要停啊。继续喷,来拓展我的世界观。
vus520
2015-12-05 18:52:16 +08:00
@looyao

我编译了一下, mac 上找不到 sys/inotify.h

不过却找到了这个东西
https://github.com/facebook/watchman
looyao
2015-12-05 18:58:15 +08:00
@vus520 不好意思, Linux 才可以,没有说明。代码临时写的,可能不够严谨,其实就是这个意思,默认读取文件,全部读取完成后监控文件改变再读,这样。不用怕大文件,其实没什么关系。 PS :代码粘上来米有缩进,好丑,下次不粘了,哈哈。
neoblackcap
2015-12-05 18:59:17 +08:00
@vus520 inotify 是 linux 内核特性, Mac 自然没有。
aku
2015-12-05 19:33:07 +08:00
@xufang 不愿意 show code 的话, release binary 就可以了

go 的好处这时候就体现出来了
clino
2015-12-05 19:37:34 +08:00
@neoblackcap 为什么 tail 不需要用到 inotify 就可以监控文件改变呢
xufang
2015-12-05 19:38:00 +08:00
@aku 偏不,我也生气了,就一起口炮下去。
xufang
2015-12-05 19:39:50 +08:00
@clino 简单的很, 在文件尾 while(1) {read(n); sleep(m)} 就可以了, 你试下就知道
xufang
2015-12-05 19:41:59 +08:00
@clino 一个小技巧就是 read(n) 每每读不到数据的时候,以斐波那契数列的时间来 sleep ,当然这个技巧有无效果就见仁见智了。 10 年前,国外的邮件列表就对这个讨论得很充分了。
skydiver
2015-12-05 19:44:45 +08:00
@clino tail 用的就是 inotify
xufang
2015-12-05 19:49:29 +08:00
skydiver
2015-12-05 19:53:49 +08:00
@xufang 我说的 gnu 的 coreutils ,你拿个 busybox 出来做甚
xufang
2015-12-05 19:56:53 +08:00
@skydiver 呵呵,转进的好。
skydiver
2015-12-05 20:02:51 +08:00
@xufang 呵呵。 block 不送。
xufang
2015-12-05 20:04:25 +08:00
终于有人使出 block 大法了,我还以为小学生们会比较好面子的死撑的呢。
clino
2015-12-05 20:28:42 +08:00
@skydiver 我搜了一下应该两种方法都有支持,优先 inotify 不行就用 polling 的方式
skydiver
2015-12-05 20:31:20 +08:00
@clino 是的 我记得用不了 inotify 的时候会有提示 使用 polling
xufang
2015-12-05 20:34:40 +08:00
一个简单的事实: tail 的历史比 inotify 要老,所以小学生哪来的如此的自信满满?
wjchen
2015-12-05 20:52:19 +08:00
可以 hook 写文件的 api 。

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

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

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

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

© 2021 V2EX