I need to read the last added line to a log file, in realtime, and capture that line being added.
Something similar to Tail -f.
So my first attempt was to use Tail -f using NSTask.
I can’t see any output using the code below:
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);
I can see the output as expected when using:
[server setLaunchPath:@"/bin/ls"];
-
How can i capture the output of that tail NSTask?
-
Is there any alternative to this method, where I can open a stream to file and each time a line is added, output it on screen? (basic logging functionality)
This is a little tricky to do your way, as
readDataToEndOfFilewill wait untiltailcloses the output stream before returning, buttail -fnever closes the output stream (stdout). However, this is actually pretty simple to do with basic C I/O code, so I whipped up a simpleFileTailerclass that you can check out. It’s not anything fancy, but it should show you how it’s done. Here’re the sources forFileTailer.h,FileTailer.m, and a test driver.The meat of the class is pretty simple. You pass it a block, and it reads a character from the stream (if possible) and passes it to the block; if EOF has been reached, it waits a number of seconds (determined by
refresh) and then tries to read the stream again.You can call it pretty simply, like this:
(Caveat: I wrote the
FileTailerclass pretty fast, so it’s kind of ugly right now and should be cleaned up a bit, but it should serve as a decent example on how to read a file indefinitely, à latail -f.)