古玩鉴定交易买卖平台,技术专栏丨iOS中Log同步获取与重定向

书画流派 2025-01-10328未知admin
(大众古玩店爱奇艺观看)

在iOS开发的过程中,经常会使用NSLog作为调试和查看相关数据的输出口,该方法连接Xcode构建项目时能够实时输出开发者在代码线中打印的日志。但是在断开Xcode并使用真机测试的时候,经常会无法查看真机的实时日志,导致一些问题难以追查和确定,使得问题的定位与解决花费较长的时间,一定程度上影响了产品开发的进度和优化。

面对诸如此类的问题,我们可以通过Log信息的重定向等技术,让相关的Log信息转存到一个我们能够提取的地方,方便开发人员在出现问题的时候,得到详细的Log信息,快速的识别出问题的原因并修复和优化等。

古玩鉴定交易买卖平台,技术专栏丨iOS中Log同步获取与重定向

NSLog的输出到底在哪里?

在iOS的系统API中,专门提供了一个上层函数NSLog以供开发者调用并打印相关的信息,NSLog本质上是一个C函数,它的声明如下:

FOUNDATION_EXPORTvoidNSLog(NSString*format,)

系统对该函数的说明是:LogsanerrormessagetotheAppleSystemLogfacility。简单的说就是用来输出信息到标准的

Error控制台上,其内部其实是使用AppleSystemLog(asl)的API,至少iOS10以前是这样。在调试阶段,日志会输出到Xcode

中,而在真机上,会输出到系统的/var/log/syslog文件中。古玩收藏鉴定拍卖>AppleSystemLogger

我们可以通过官方文档了解到,OC中最常见的NSLog操作会同时将标准的Error输出到控制台和系统日志(syslog)中(C语言的printf系列函数并不会,swift的printf为了保证性能也只会在模拟器环境中输出)。其内部是使用AppleSystemLogger(简称ASL)去实现的,ASL是苹果自己实现的用于输出日志到系统日志库的一套API接口,有点类似于SQL操作。在iOS真机设备上,使用ASL记录的log被缓存在沙盒文件中,直到设备被重启。

既然日志被写入系统的syslog中,那我们可以直接读取这些日志。从ASL读取日志的核心代码如下:

注:滑动查看完整代码(下同)

1definestdinstdinp

definestderrstderrp

其对应的三个iOS版本的文件句柄是(定义在文件中):


在使用重定向之后,NSLog就不会写到系统的syslog中了。

dup2重定向

通过重定向,可以直接截取stdout,stderr等标准输出的信息,然后保存在想要存储的位置,上传到服务器或者显示到View上。要做到重定向,需要通过NSPipe创建一个管道,pipe有读端和写端,然后通过dup2将标准输入重定向到pipe的写端。再通

过NSFileHandle监听pipe的读端,最后再处理读出的信息。之后通过printf或者NSLog写数据,都会写到pipe的写端,同时

pipe会将这些数据直接传送到读端,最后通过NSFileHandle的监控函数取出这些数据。核心代码如下:

1-(void)redirectStandardOutput{2//记录标准输出及错误流原始文件描述符3=dup(STDOUT_FILENO);=dup(STDERR_FILENO);4if19}2025-(void)recoverStandardOutput{22if26}2728//重定向之后的NSLog输出29-(void)redirectOutNotificationHandle:(NSNotification*)nf{if33[[nfobject]readInBackgroundAndNotify];34}3536//重定向之后的错误输出37-(void)redirectErrNotificationHandle:(NSNotification*)nf{if41[[nfobject]readInBackgroundAndNotify];42}

dup函数可以为我们复制一个文件描述符,传给该函数一个既有的描述符,它就会返回一个新的描述符,这个新的描述符是传给它的描述符的拷贝。这意味着,这两个描述符共享同一个数据结构。

而dup2函数跟dup函数相似,但dup2函数允许调用者规定一个有效描述符和目标描述符的id。dup2函数成功返回时,目标描述符(dup2函数的第二个参数)将变成源描述符(dup2函数的第一个参数)的复制品,换句话说,两个文件描述符现在都指向同一个文件,并且是函数第一个参数指向的文件。

文件重定向

另一种重定向的方式是利用c语言的freopen函数进行重定向,将写往stderr的内容重定向到我们制定的文件中去,一旦执行了上述代码那么在这个之后的NSLog将不会在控制台显示了,会直接输出在指定的文件中。在模拟器中,我们可以使用终端

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

FILE*freopen(constchar*filename,constchar*mode,FILE*stream);

核心代码如下:

1NSArray*paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);NSString*documentsPath=[pathsobjectAtIndex:0];2NSString*loggingPath=[documentsPathstringByAppingPathComponent:@"/"];3//redirectNSLog4freopen([loggingPathcStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);

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

1//重定向2intorigin1=dup(STDERR_FILENO);3FILE*myFile=freopen([loggingPathcStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);45//恢复重定向6dup2(origin1,STDERR_FILENO);
使用GCD的dispatchSource重定向方式

具体代码如下:

1-(dispatch_source_t)_startCapturingWritingToFD:(int)fd{2intfildes[2];3pipe(fildes);//[0]isreadofpipewhile[1]iswritedup2(fildes[1],fd);//Duplicatewriteofpipe"onto"fd(thisclosesfd)close(fildes[1]);//Closeoriginalwriteofpipe4fd=fildes[0];//Wecannowmonitorthereadofthepipe5char*buffer=malloc(1024);6NSMutableData*data=[[NSMutableDataalloc]init];fcntl(fd,F_SETFL,O_NONBLOCK);7dispatch_source_tsource=dispatch_source_create(8DISPATCH_SOURCE_TYPE_READ,fd,0,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0));dispatch_source_set_cancel_handler(source,^{9free(buffer);10});11dispatch_source_set_event_handler(source,^{@autoreleasepool{1213while(1){14ssize_tsize=read(fd,buffer,1024);15if(size=0){16break;17}18[dataappBytes:bufferlength:size];19if(size1024){20break;21}22}232425262728}29});3031NSString*aString=[[NSStringalloc]initWithData:dataencoding:NSUTF8StringEncoding];32//printf("aString=%s",[aStringUTF8String]);33//NSLog(@"aString=%@",aString);34//Dosomething3536dispatch_resume(source);37returnsource;38}39
总结

虽然上述的几个重定向的方法都能够获取到Log数据,但是弊端是当使用Log重定向之后,连接Xcode进行调试应用程序时,Xcode的Console中将不会打印任何Log信息,Log信息已经被重定向到了我们指定的文件中了。

这些方法有一定的局限性,在具体使用的时候,需要视情况而定。当然还有其他的方式能够即重定向Log数据到指定文件,还能够在Xcode的Console中输出日志(pipe、dup2与GCD的相互协作),这样能够避免调试阶段无法实时查看日志的缺陷,进一步的提高开发调试和优化的效率。

另外也可以开发一个在桌面或者网页端实时展示Log信息的应用,实时从重定向的位置读取Log信息,达到实时查看信息的目的等。

p[古玩杂项入门书籍]

孕喏生殖中心 Copyright © 2002-2030  代怀生子机构_『三甲医院合作』_国内正规代生(孕)公司_孕喏生殖中心 sitemap.xml