Android log抓取工具

版权声明:欢迎转载 https://blog.csdn.net/qq_33242956/article/details/89213724

工作需要抓取Android Log,Linux下使用命令行比较麻烦,弄了一个工具比较方便的抓取和存储Log

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>

typedef enum LOG_RES_DEF {
    LOG_RES_SUCCESS,
    LOG_RES_FAILED,
} LOG_RES_DEF_T;

typedef enum LOG_TYPE {
    LOG_TYPE_UNKNOW = 0,
    LOG_TYPE_CA = 1000,
    LOG_TYPE_TA = 1001,
    LOG_TYPE_KERNEL = 1002,
} LOG_TYPE_T;

#define BOOL unsigned int
#define TRUE 1
#define FALSE 0
#define MAX_PARAMETER_COUNT 5
#define MAX_DATA_SIZE 1024

typedef struct parm_def {
    int log_type;
    BOOL case_sensitive;
    BOOL save_all_log;
    char log_tag[MAX_DATA_SIZE];
} parm_def_t;

static const char *g_parm_array[MAX_PARAMETER_COUNT] = {"c", "t", "k", "i", "a"};
static parm_def_t g_parm_def;

static void help_info();
static int parm_convert(const char *parm_data, int parm_data_len);
static int check_parm(int argc, char const *argv[]);
static int create_pthread(char *in_data);
static void log_shell(const char *format, ...);
static void get_local_time(char *time_data);
static void *pthread_show_log(void *in_data);
static void *pthread_save_log(void *in_data);

static void help_info()
{
    printf("[-c] print logcat android log\n");
    printf("[-t] print fingerprint ta log\n");
    printf("[-k] print kernel log\n");
    printf("[-i] Case-sensitive\n");
    printf("[-a] Save all log\n");
    printf("[-clean] Clear all saved logs\n");
    printf("ex: log -cia 'goodix|fingerprintservice|fingerprintmanager'\n");
}

static int parm_convert(const char *parm_data, int parm_data_len)
{
    int index, array_index;
    //printf("parm_data:%s parm_data_len:%d\n", parm_data, parm_data_len);
    for (index = 1; index < parm_data_len; index++) {
        if (!memcmp(&parm_data[index], g_parm_array[0], strlen(g_parm_array[0]))) {
            if (g_parm_def.log_type == LOG_TYPE_UNKNOW) {
                g_parm_def.log_type = LOG_TYPE_CA;
            }
        } else if (!memcmp(&parm_data[index], g_parm_array[1], strlen(g_parm_array[1]))) {
            if (g_parm_def.log_type == LOG_TYPE_UNKNOW) {
                g_parm_def.log_type = LOG_TYPE_TA;
            }
        } else if (!memcmp(&parm_data[index], g_parm_array[2], strlen(g_parm_array[2]))) {
            if (g_parm_def.log_type == LOG_TYPE_UNKNOW) {
                g_parm_def.log_type = LOG_TYPE_KERNEL;
            }
        } else if (!memcmp(&parm_data[index], g_parm_array[3], strlen(g_parm_array[3]))) {
            g_parm_def.case_sensitive = TRUE;
        } else if (!memcmp(&parm_data[index], g_parm_array[4], strlen(g_parm_array[4]))) {
            g_parm_def.save_all_log = TRUE;
        } else {
            printf("Unknown option: -%c\n", parm_data[index]);
            printf("usage: [-c] [-t] [-k], you can use [-help] to see all option\n");
            return LOG_RES_FAILED;
        }
    }

    return LOG_RES_SUCCESS;
}

static int check_parm(int argc, char const *argv[])
{
    int result = LOG_RES_SUCCESS;
    int find_index;
    int parm_index;
    memset(&g_parm_def, 0x00, sizeof(parm_def_t));

    if (argc <= 1) {
        printf("Unknown option: \n");
        printf("usage: [-c] [-t] [-k], you can use [-help] to see all option\n");
        return LOG_RES_FAILED;
    }

    if (!memcmp(argv[1], "-help", strlen("-help"))) {
        help_info();
        return LOG_RES_FAILED;
    }

    if (!memcmp(argv[1], "-clean", strlen("-clean"))) {
        system("rm ~/log-dir/*.log");
        return LOG_RES_FAILED;
    }

    for (parm_index = 1; parm_index < argc; parm_index++) {
        if (!memcmp(argv[parm_index], "-", strlen("-"))) {
            //printf("argv[%d] = %s\n", parm_index, argv[parm_index]);
            if (parm_convert(argv[parm_index], strlen(argv[parm_index])) != LOG_RES_SUCCESS) {
                result = LOG_RES_FAILED;
                break;
            }
        } else {
            memcpy(g_parm_def.log_tag, argv[parm_index], strlen(argv[parm_index]));
        }
    }

    /* printf("g_parm_def.log_type = %d\n", g_parm_def.log_type);
    printf("g_parm_def.case_sensitive = %d\n", g_parm_def.case_sensitive);
    printf("g_parm_def.save_all_log = %d\n", g_parm_def.save_all_log);
    printf("g_parm_def.log_tag = %s\n", g_parm_def.log_tag); */

    return result;
}

static int create_pthread(char *in_data)
{
    pthread_t t_id[2];
    void *result;

    if(pthread_create(&t_id[0], NULL, pthread_show_log, in_data) == -1){
        printf("create pthread_show_log failed!\n");
        return LOG_RES_FAILED;
    }

    if(pthread_create(&t_id[1], NULL, pthread_save_log, in_data) == -1){
        printf("create pthread_save_log failed!\n");
        return LOG_RES_FAILED;
    }

    if(pthread_join(t_id[0], &result) == -1){
        printf("pthread_show_log join failed!\n");
        return LOG_RES_FAILED;
    }

    if(pthread_join(t_id[1], &result) == -1){
        printf("pthread_save_log join failed!\n");
        return LOG_RES_FAILED;
    }

    return LOG_RES_SUCCESS;
}

static void log_shell(const char *format, ...)
{
    char string[MAX_DATA_SIZE] = {0};

    va_list args;
    va_start(args, format);
    vsnprintf(string, MAX_DATA_SIZE, format, args);
    va_end(args);

    printf("string: %s\n", string);

    system(string);
}

static void get_local_time(char *time_data)
{
    time_t timep;
    struct tm *ptr_tm;
    time(&timep);
    ptr_tm = gmtime(&timep);

    sprintf(time_data, "%d%02d%02d_%02d%02d%02d", 1900 + ptr_tm->tm_year, 1 + ptr_tm->tm_mon, ptr_tm->tm_mday, 8 + ptr_tm->tm_hour, ptr_tm->tm_min,  ptr_tm->tm_sec);
}

void *pthread_show_log(void *in_data)
{
    parm_def_t *parm_data = (parm_def_t *)(in_data);
    printf("log_type: %d log_tag: %s\n", parm_data->log_type, parm_data->log_tag);

    log_shell("touch log_tag.txt; echo '%s' >> ~/log-dir/log_tag.txt", parm_data->log_tag);

    if (strlen(parm_data->log_tag) == 0) {
        switch (parm_data->log_type) {
            case LOG_TYPE_CA: {
                log_shell("adb logcat -v threadtime");
            } break;

            case LOG_TYPE_TA: {
                log_shell("adb shell cat /d/tzdbg/qsee_log");
            } break;

            case LOG_TYPE_KERNEL: {
                log_shell("while true; do adb shell cat /proc/kmsg; done");
            } break;
        
            default: {
                printf("log_type error: %d!\n", parm_data->log_type);
            } break;
        }
    } else {
        switch (parm_data->log_type) {
            case LOG_TYPE_CA: {
                if (parm_data->case_sensitive) {
                    log_shell("adb logcat -v threadtime | grep --color=auto -E '%s'", parm_data->log_tag);
                } else {
                    log_shell("adb logcat -v threadtime | grep --color=auto -i -E '%s'", parm_data->log_tag);
                }
            } break;

            case LOG_TYPE_TA: {
                if (parm_data->case_sensitive) {
                    log_shell("adb shell cat /d/tzdbg/qsee_log | grep --color=auto -E '%s'", parm_data->log_tag);
                } else {
                    log_shell("adb shell cat /d/tzdbg/qsee_log | grep --color=auto -i -E '%s'", parm_data->log_tag);
                }
            } break;

            case LOG_TYPE_KERNEL: {
                if (parm_data->case_sensitive) {
                    log_shell("while true; do adb shell cat /proc/kmsg | grep --color=auto -E '%s'; done", parm_data->log_tag);
                } else {
                    log_shell("while true; do adb shell cat /proc/kmsg | grep --color=auto -i -E '%s'; done", parm_data->log_tag);
                }
            } break;
        
            default: {
                printf("log_type error: %d!\n", parm_data->log_type);
            } break;
        }
    }
}

void *pthread_save_log(void *in_data)
{
    char time_data[MAX_DATA_SIZE] = {0};
    parm_def_t *parm_data = (parm_def_t *)(in_data);
    printf("log_type: %d log_tag: %s save_all_log: %d\n", parm_data->log_type, parm_data->log_tag, parm_data->save_all_log);

    get_local_time(time_data);

    if (parm_data->save_all_log || strlen(parm_data->log_tag) == 0) {
        switch (parm_data->log_type) {
            case LOG_TYPE_CA: {
                log_shell("adb logcat -v threadtime >> ~/log-dir/ca_%s.log", time_data);
            } break;

            case LOG_TYPE_TA: {
                log_shell("adb shell cat /d/tzdbg/qsee_log >> ~/log-dir/ta_%s.log", time_data);
            } break;

            case LOG_TYPE_KERNEL: {
                log_shell("while true; do adb shell cat /proc/kmsg >> ~/log-dir/kernel_%s.log; done", time_data);
            } break;
        
            default: {
                printf("log_type error: %d!\n", parm_data->log_type);
            } break;
        }
    } else {
        switch (parm_data->log_type) {
            case LOG_TYPE_CA: {
                if (parm_data->case_sensitive) {
                    log_shell("adb logcat -v threadtime | grep --color=auto -E '%s' >> ~/log-dir/ca_%s.log", parm_data->log_tag, time_data);
                } else {
                    log_shell("adb logcat -v threadtime | grep --color=auto -i -E '%s' >> ~/log-dir/ca_%s.log", parm_data->log_tag, time_data);
                }
            } break;

            case LOG_TYPE_TA: {
                if (parm_data->case_sensitive) {
                    log_shell("adb shell cat /d/tzdbg/qsee_log | grep --color=auto -E '%s' >> ~/log-dir/ta_%s.log", parm_data->log_tag, time_data);
                } else {
                    log_shell("adb shell cat /d/tzdbg/qsee_log | grep --color=auto -i -E '%s' >> ~/log-dir/ta_%s.log", parm_data->log_tag, time_data);
                }
            } break;

            case LOG_TYPE_KERNEL: {
                if (parm_data->case_sensitive) {
                    log_shell("while true; do adb shell cat /proc/kmsg | grep --color=auto -E '%s'; done >> ~/log-dir/kernel_%s.log; done", parm_data->log_tag, time_data);
                } else {
                    log_shell("while true; do adb shell cat /proc/kmsg | grep --color=auto -i -E '%s'; done >> ~/log-dir/kernel_%s.log; done", parm_data->log_tag, time_data);
                }
            } break;
        
            default: {
                printf("log_type error: %d!\n", parm_data->log_type);
            } break;
        }
    }
}

int main(int argc, char const *argv[])
{
    if (check_parm(argc, argv) != LOG_RES_SUCCESS) {
        return 0;
    }

    system("adb root; adb remount; adb shell setenforce 0");

    if (create_pthread((void *)&g_parm_def) != LOG_RES_SUCCESS) {
        return 0;
    }

    return 0;
}

编译命令:gcc log.c -lpthread -o logfilter

与指纹相关的Log有3种,Android CA Log、TEE Log、kernel Log。命令参数对应如下:
1、-c:Android logcat输出的Log,包含Android上层的所有Log
2、-t:TEE下的所有的Log
3、-k:kernel的Log
4、-i:显示的Log不需要筛选关键词
5、-a:存储的Log不需要筛选关键词
6、-clean:删除Log存储目录下的所有Log文件
7、-help:输出帮助信息
另外在Log存储目录下有log_tag.txt文件用来存储所有曾使用过的筛选关键词
使用命令:logfilter -ca ‘fingerprintservice|FingerprintManager’ 打印只包含"fingerprintservice|FingerprintManager"的Log但是存储的是全部的CA Log
PS:有时间弄成一个带界面的动态实时筛选抓取工具

猜你喜欢

转载自blog.csdn.net/qq_33242956/article/details/89213724