2015-02-24 60 views
3

this app "System Console"(由一家名为Electric Labs Ltd的公司制造)如何访问iOS 8上的设备日志?Api来读取iOS设备上的日志8

我试图做同样的事情,但我得到的是我自己的应用程序的日志消息。 我使用Apple System Logging facility的api作为this article "Accessing the iOS System Log"的示例。

我知道,由于iOS 7+中的沙盒子系统,我的应用只能看到自己的日志消息。但我想知道“系统控制台”应用程序如何避免这种限制?

+0

这是完全有可能的是,系统控制台使用非公开的API,因为它是开发由Apple。 – 2015-02-24 00:21:50

+0

[系统控制台](https://itunes.apple.com/us/app/system-console/id431158981?mt=8)不是由Apple开发,而是由一家名为Electric Labs的公司开发的。 – 2015-02-24 09:29:22

+0

这个问题现在对我更有意义。 – 2015-02-24 17:05:51

回答

5

看来你可以阅读“syslog.sock”。我在Github上找到了一个适用于iOS8的项目:https://github.com/eswick/ondeviceconsole

我创建了以下测试代码(空项目)并运行它以查看控制台中的当前日志记录信息。它承认启动邮件应用程序,Notes应用程序等。信息需要解析,但这是一个不同的问题。 (警告:恶心下面的代码!)使用为好,不邪恶;)

// 
// ViewController.m 
// LogTest 
// 
// Created by Freek Sanders on 26-02-15. 

#import "ViewController.h" 
#import <asl.h> 

#import <sys/socket.h> 
#import <sys/un.h> 

#import <unistd.h> 
#import <fcntl.h> 
#import <poll.h> 



#define SOCKET_PATH "/var/run/lockdown/syslog.sock" 

#define COLOR_RESET   "\e[m" 
#define COLOR_NORMAL  "\e[0m" 
#define COLOR_DARK   "\e[2m" 
#define COLOR_RED   "\e[0;31m" 
#define COLOR_DARK_RED  "\e[2;31m" 
#define COLOR_GREEN   "\e[0;32m" 
#define COLOR_DARK_GREEN "\e[2;32m" 
#define COLOR_YELLOW  "\e[0;33m" 
#define COLOR_DARK_YELLOW "\e[2;33m" 
#define COLOR_BLUE   "\e[0;34m" 
#define COLOR_DARK_BLUE  "\e[2;34m" 
#define COLOR_MAGENTA  "\e[0;35m" 
#define COLOR_DARK_MAGENTA "\e[2;35m" 
#define COLOR_CYAN   "\e[0;36m" 
#define COLOR_DARK_CYAN  "\e[2;36m" 
#define COLOR_WHITE   "\e[0;37m" 
#define COLOR_DARK_WHITE "\e[0;37m" 

@interface ViewController() 

@end 

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    int nfd = unix_connect(SOCKET_PATH); 

    // write "watch" command to socket to begin receiving messages 
    write(nfd, "watch\n", 6); 

    struct pollfd pfd[2]; 
    unsigned char buf[16384]; 
    int n = fileno(stdin); 
    int lfd = fileno(stdout); 
    int plen = 16384; 

    pfd[0].fd = nfd; 
    pfd[0].events = POLLIN; 

    while (pfd[0].fd != -1) { 

     if ((n = poll(pfd, 1, -1)) < 0) { 
      close(nfd); 
      perror("polling error"); 
      exit(1); 
     } 

     if (pfd[0].revents & POLLIN) { 
      if ((n = read(nfd, buf, plen)) < 0) 
       perror("read error"), exit(1); /* possibly not an error, just disconnection */ 
      else if (n == 0) { 
       shutdown(nfd, SHUT_RD); 
       pfd[0].fd = -1; 
       pfd[0].events = 0; 
      } else { 
       if (atomicio(write_colored, lfd, buf, n) != n) 
        perror("atomicio failure"), exit(1); 
      } 
     } 
    } 
} 

size_t atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n) 
{ 
    char *s = _s; 
    size_t pos = 0; 
    ssize_t res; 
    struct pollfd pfd; 

    pfd.fd = fd; 
    pfd.events = f == read ? POLLIN : POLLOUT; 
    while (n > pos) { 
     res = (f) (fd, s + pos, n - pos); 
     switch (res) { 
      case -1: 
       if (errno == EINTR) 
        continue; 
       if ((errno == EAGAIN) || (errno == ENOBUFS)) { 
        (void)poll(&pfd, 1, -1); 
        continue; 
       } 
       return 0; 
      case 0: 
       errno = EPIPE; 
       return pos; 
      default: 
       pos += (size_t)res; 
     } 
    } 
    return (pos); 
} 

int unix_connect(char* path) { 
    struct sockaddr_un sun; 
    int s; 

    if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 
     return (-1); 
    (void)fcntl(s, F_SETFD, 1); 

    memset(&sun, 0, sizeof(struct sockaddr_un)); 
    sun.sun_family = AF_UNIX; 

    if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) { 
     close(s); 
     errno = ENAMETOOLONG; 
     return (-1); 
    } 
    if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { 
     close(s); 
     return (-1); 
    } 

    return (s); 
} 

#define LINE_REGEX "(\\w+\\s+\\d+\\s+\\d+:\\d+:\\d+)\\s+(\\S+|)\\s+(\\w+)\\[(\\d+)\\]\\s+\\<(\\w+)\\>:\\s(.*)" 

ssize_t write_colored(int fd, void* buffer, size_t len) { 

    char *escapedBuffer = malloc(len + 1); 
    memcpy(escapedBuffer, buffer, len); 
    escapedBuffer[len] = '\0'; 

    NSString *str = [NSString stringWithUTF8String:escapedBuffer]; 
    free(escapedBuffer); 

    NSError *error = nil; 
    NSRegularExpression *regex = [NSRegularExpression 
            regularExpressionWithPattern:@LINE_REGEX 
            options:NSRegularExpressionCaseInsensitive 
            error:&error]; 

    NSArray *matches = [regex matchesInString:str 
             options:0 
             range:NSMakeRange(0, [str length])]; 

    if ([matches count] == 0) 
     return write(fd, buffer, len); 

    for (NSTextCheckingResult *match in matches) { 

     if ([match numberOfRanges] < 6) { 
      write(fd, buffer, len); // if entry doesn't match regex, print uncolored 
      continue; 
     } 

     NSRange dateRange = [match rangeAtIndex:1]; 
     NSRange deviceRange = [match rangeAtIndex:2]; 
     NSRange processRange = [match rangeAtIndex:3]; 
     NSRange pidRange  = [match rangeAtIndex:4]; 
     NSRange typeRange = [match rangeAtIndex:5]; 
     NSRange logRange  = [match rangeAtIndex:6]; 

     NSString *date  = [str substringWithRange:dateRange]; 
     NSString *device  = [str substringWithRange:deviceRange]; 
     NSString *process = [str substringWithRange:processRange]; 
     NSString *pid  = [str substringWithRange:pidRange]; 
     NSString *type  = [str substringWithRange:typeRange]; 
     NSString *log  = [str substringWithRange: 
           NSMakeRange(logRange.location, 
              [str length] - logRange.location)]; 

     log = [log stringByTrimmingCharactersInSet: 
       [NSCharacterSet newlineCharacterSet]]; 

     NSMutableString *build = [NSMutableString new]; 

     [build appendString:@COLOR_DARK_WHITE]; 
     [build appendString:date]; 
     [build appendString:@" "]; 
     [build appendString:device]; 
     [build appendString:@" "]; 

     [build appendString:@COLOR_CYAN]; 
     [build appendString:process]; 
     [build appendString:@"["]; 
     [build appendString:pid]; 
     [build appendString:@"]"]; 

     char *typeColor = COLOR_DARK_WHITE; 
     char *darkTypeColor = COLOR_DARK_WHITE; 

     if ([type isEqualToString:@"Notice"]) { 
      typeColor = COLOR_GREEN; 
      darkTypeColor = COLOR_DARK_GREEN; 
     } else if ([type isEqualToString:@"Warning"]) { 
      typeColor = COLOR_YELLOW; 
      darkTypeColor = COLOR_DARK_YELLOW; 
     } else if ([type isEqualToString:@"Error"]) { 
      typeColor = COLOR_RED; 
      darkTypeColor = COLOR_DARK_RED; 
     } else if ([type isEqualToString:@"Debug"]) { 
      typeColor = COLOR_MAGENTA; 
      darkTypeColor = COLOR_DARK_MAGENTA; 
     } 

     [build appendString:@(darkTypeColor)]; 
     [build appendString:@" <"]; 
     [build appendString:@(typeColor)]; 
     [build appendString:type]; 
     [build appendString:@(darkTypeColor)]; 
     [build appendString:@">"]; 
     [build appendString:@COLOR_RESET]; 
     [build appendString:@": "]; 
     [build appendString:log]; 

     printf("%s\n", [build UTF8String]); 
    } 

    return len; 
} 

@end 
+0

您从其他应用看到多少? – ahwulf 2015-02-26 14:46:32

+0

不确定。试一试;) – 2015-02-26 20:36:13

+0

对不起,迟到的回应。没有时间来测试你的例子。你确定这可以在没有越狱的设备上使用吗? – 2015-03-02 11:17:51

0

请参见下面的代码:

aslmsg q, m; 
int i; 
const char *key, *val; 
q = asl_new(ASL_TYPE_QUERY); 
aslresponse r = asl_search(NULL, q); 
while (NULL != (m = aslresponse_next(r))) 
{ 
    NSMutableDictionary *tmpDict = [NSMutableDictionary dictionary]; 
    for (i = 0; (NULL != (key = asl_key(m, i))); i++) 
    { 
     NSString *keyString = [NSString stringWithUTF8String:(char *)key]; 
     val = asl_get(m, key); 
     NSString *string = val?[NSString stringWithUTF8String:val]:@""; 
     [tmpDict setObject:string forKey:keyString]; 
    } 
    NSLog(@"%@", tmpDict); 
} 
aslresponse_free(r); 
+0

自iOS 7开始,此方法不再有效。您只能读取自己的日志条目。 – 2015-03-11 13:06:56

+0

这是我第一次尝试的方法(我在我的问题中提到过)。我在寻找替代品,因为iOS7 +上的ASL仅允许访问由您自己的应用程序创建的消息日志(您无法看到由其他应用程序创建的消息日志)。这是因为iOS7中引入了沙盒系统。 @Freek Sanders给出的例子适用于iOS7 +。 – 2015-03-11 15:19:16