iOS中日志同步获取NSLog重定向以及其他详解

2020-01-21 03:11:26王冬梅

在模拟器中,我们可以使用终端的tail命令(tail -f xxx.log)对这个文件进行实时查看,就如同我们在Xcode的输出窗口中看到的那样,你还可以结合grep命令进行实时过滤查看,非常方便在大量的日志信息中迅速定位到我们要的日志信息。


FILE * freopen ( const char * filename, const char * mode, FILE * stream );

具体代码如下:


NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *loggingPath = [documentsPath stringByAppendingPathComponent:@"/xxx.log"];
//redirect NSLog
freopen([loggingPath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr);

这样我们就可以把可获取的日志文件发送给服务端或者通过itunes共享出来。但是由于iOS严格的沙盒机制,我们无法知道stderr原来的文件路径,也无法直接使用沙盒外的文件,所以freopen无法重定向回去,只能使用第1点所述的dup和dup2来实现。


// 重定向
int origin1 = dup(STDERR_FILENO);
FILE * myFile = freopen([loggingPath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr);
// 恢复重定向
dup2(origin1, STDERR_FILENO);

使用GCD的dispatch Source重定向方式

具体代码如下:


- (dispatch_source_t)_startCapturingWritingToFD:(int)fd {
 int fildes[2];
 pipe(fildes); // [0] is read end of pipe while [1] is write end
 dup2(fildes[1], fd); // Duplicate write end of pipe "onto" fd (this closes fd)
 close(fildes[1]); // Close original write end of pipe
 fd = fildes[0]; // We can now monitor the read end of the pipe
 char* buffer = malloc(1024);
 NSMutableData* data = [[NSMutableData alloc] init];
 fcntl(fd, F_SETFL, O_NONBLOCK);
 dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
 dispatch_source_set_cancel_handler(source, ^{
  free(buffer);
 });
 dispatch_source_set_event_handler(source, ^{
  @autoreleasepool {
   while (1) {
    ssize_t size = read(fd, buffer, 1024);
    if (size <= 0) {
     break;
    }
    [data appendBytes:buffer length:size];
    if (size < 1024) {
     break;
    }
   }
   NSString *aString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
   //printf("aString = %s",[aString UTF8String]);
   //NSLog(@"aString = %@",aString);
   // Do something
  }
 });
 dispatch_resume(source);
 return source;
}

日志同步/上传

重定向或者存储的数据可以传到服务端或者通过server同步到网页上,就可以更方便的看到这些数据了。

如果想再网页端实时查看日志,可以在App内置一个小型http web服务器。GitHub上开源的项目有GCDWebServer,可以使用该工具,在APP开启webserver服务,并在同一局域网下,使用http://localhost:8080来请求最新日志了。