工作需要抓取Android Log,Linux下使用命令行比较麻烦,弄了一个工具比较方便的抓取和存储Log
#include
#include
#include
#include
#include
#include
#include
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:有动态抓取log的工具logfilter,Linux下可以完美运行,不过将系统语言设置为英文UI界面会好看一些