4

我需要将最后添加的行实时读取到日志文件中,并捕获正在添加的行。

类似于 Tail -f 的东西。

所以我的第一次尝试是通过 NSTask 使用 Tail -f。

使用下面的代码我看不到任何输出:

    NSTask *server = [[NSTask alloc] init];
    [server setLaunchPath:@"/usr/bin/tail"];
    [server setArguments:[NSArray arrayWithObjects:@"-f", @"/path/to/my/LogFile.txt",nil]];

    NSPipe *outputPipe = [NSPipe pipe];
    [server setStandardInput:[NSPipe pipe]];
    [server setStandardOutput:outputPipe];

    [server launch];
    [server waitUntilExit];
    [server release];

    NSData *outputData = [[outputPipe fileHandleForReading] readDataToEndOfFile];
    NSString *outputString = [[[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding] autorelease];
    NSLog (@"Output \n%@", outputString);

使用时我可以看到预期的输出:

[server setLaunchPath:@"/bin/ls"];
  1. 我如何捕获该尾部 NSTask 的输出?

  2. 这种方法是否有任何替代方法,我可以在其中打开文件流,并且每次添加一行时,将其输出到屏幕上?(基本的日志记录功能)

4

2 回答 2

5

这有点棘手,因为readDataToEndOfFile会等到tail关闭输出流后再返回,但tail -f永远不会关闭输出流(stdout)。然而,这对于基本的 CI/O 代码来说实际上非常简单,所以我创建了一个简单的FileTailer类,您可以查看它。这不是什么花哨的东西,但它应该向您展示它是如何完成的。FileTailer.h以下是、FileTailer.m测试驱动程序的来源。

这门课的内容很简单。您将一个块传递给它,它会从流中读取一个字符(如果可能的话)并将其传递给块;如果已达到 EOF,它会等待几秒钟(由 确定refresh),然后尝试再次读取流。

- (void)readIndefinitely:(void (^)(int ch))action
{
    long pos = 0L;
    int ch = 0;

    while (1) {
        fseek(in, pos, SEEK_SET);
        int ch = fgetc(in);
        pos = ftell(in);
        if (ch != EOF) {
            action(ch);
        } else {
            [NSThread sleepForTimeInterval:refresh];
        }
    }
}

您可以非常简单地调用它,如下所示:

FileTailer *tail = [[[FileTailer alloc] initWithStream:stdin refreshPeriod:3.0] autorelease];
[tail readIndefinitely:^ void (int ch) { printf("%c", ch); }];

(警告:我写这FileTailer门课的速度非常快,所以它现在有点难看,应该稍微清理一下,但它应该作为如何无限期读取文件的一个不错的例子,à la tail -f。)

于 2011-01-12T23:08:29.580 回答
1

这是在 Objective-C 中通过 NSTask 使用“tail -f logfile”的一种方法:

asynctask.m -- 示例代码,展示了如何实现异步标准输入、标准输出和标准错误流以使用 NSTask 处理数据

...

作为无 GUI 的应用程序(即基于 Foundation 的命令行工具),asynctask.m 手动运行 NSRunLoop 以启用异步“waitForDataInBackgroundAndNotify”通知的使用。此外,asynctask.m 使用 pthread_create(3) 和 pthread_detach(3) 将超过 64 KB 的数据写入 NSTask 的标准输入。

asynctask.m 的源代码在:http ://www.cocoadev.com/index.pl?NSPipe

于 2011-01-14T13:49:16.257 回答