jjzjj

ios - 在 iOS 8 上读取设备日志的 API

coder 2024-01-10 原文

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

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

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

最佳答案

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

我创建了以下测试代码(空项目)并运行它以查看控制台中的当前日志记录信息。它识别启动邮件应用程序、笔记应用程序等。信息需要解析,但这是一个不同的问题。 (警告:下面令人作呕的代码!)善用而非邪恶;)

//
//  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

关于ios - 在 iOS 8 上读取设备日志的 API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28686055/

有关ios - 在 iOS 8 上读取设备日志的 API的更多相关文章

  1. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  2. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  3. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  4. ruby-on-rails - ActionController::RoutingError: 未初始化常量 Api::V1::ApiController - 2

    我有用于控制用户任务的Rails5API项目,我有以下错误,但并非总是针对相同的Controller和路由。ActionController::RoutingError:uninitializedconstantApi::V1::ApiController我向您描述了一些我的项目,以更详细地解释错误。应用结构路线scopemodule:'api'donamespace:v1do#=>Loginroutesscopemodule:'login'domatch'login',to:'sessions#login',as:'login',via::postend#=>Teamroutessc

  5. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  6. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  7. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  8. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  9. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  10. ruby-on-rails - Mandrill API 模板 - 2

    我正在使用Mandrill的RubyAPIGem并使用以下简单的测试模板:testastic按照Heroku指南中的示例,我有以下Ruby代码:require'mandrill'm=Mandrill::API.newrendered=m.templates.render'test-template',[{:header=>'someheadertext',:main_section=>'Themaincontentblock',:footer=>'asdf'}]mail(:to=>"JaysonLane",:subject=>"TestEmail")do|format|format.h

随机推荐