Android日志分析系统复盘

搭建一个HTTP后台服务,(网络库,线程安全)
根据提供的URL,下载日志压缩包,(下载服务,wget)
然后进行压缩包的解压操作。(解压服务,tar、7z)
解压之后,编写脚本程序统计日志文件数目、分类。(脚本编程,Shell)
使用检索工具,解析日志的关键内容。(检索,rg)

目前支持解析的日志类型

  1. anr、tombstone的数目
  2. logdump、kernel log、tombstone的具体事件
    1. 均已支持检索正则表达式及显示其原句
  3. dropbox panic字眼

问题解决 - 报文拆分、超频重发

响应的消息要发到企业微信API。
每次的消息都有长度限制为5120个字符,如果超过了限制就需要做一个报文拆分处理

虽然企业微信api发送成功率很高,但是服务器也有必要确认客户端收到了消息,直到收到回发的ok才放心。

按目前项目要处理的内容的体量来说不那么紧要,但是对于可能扩大规模很有必要,
企业微信接口每分钟只能发20条消息,如果收到超频率应答,需要阻塞1分钟重发。总的来说,需要完善一下系统的确认应答机制。

三种异常处理:分包、循环+重传递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 查项目目前支持的errcode表
if(WorkWXErrCodeErrMsg.find(receivedJson["errcode"]) != WorkWXErrCodeErrMsg.end())
{
// 接收到ok报文,即客户端确认收到
if(receivedJson["errcode"] == 0){
return true;
}
else // 异常处理
{
LOG_ERROR << "WorkWX API Return Json ErrMsg: " << string(receivedJson["errmsg"]);
// 超长,分包处理
if(receivedJson["errcode"] == WorkWXErrCode::MSG_OUT_OF_LENGTH)
{
vector<json> splitContentJsonVec;
SplitJsonMsgPack(splitContentJsonVec, contentJson, fileName);
for(const auto & pack : splitContentJsonVec)
{
if(!SendJsonToWX(webhook, fileName, pack, level + 1))
{
LOG_ERROR << "Failed to send split message pack, contentJson was log to the file.";
LOG_ERROR << contentJson.dump();
return false;
}
}
return true;
}// 企业微信api规定1分钟只能发20条消息。超频,阻塞1min处理
else if(receivedJson["errcode"] == WorkWXErrCode::FREQ_OUT_OF_LIMIT){
sleep(60);
return SendJsonToWX(webhook, fileName, contentJson, level + 1);
}// 微信系统繁忙,超时,阻塞level min重发
else if(receivedJson["errcode"] == WorkWXErrCode::BUSY){
sleep(level * 60);
return SendJsonToWX(webhook, fileName, contentJson, level + 1);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void SplitJsonMsgPack(vector<json> & jsonVec, const json &j, const string &fileName)
{
string msgtype = j["msgtype"];
string content = j[msgtype]["content"];
//每个包加 文件名+count(页数) 因为不能超过4096个所以此处抽出72个字节存放包名
for(int count = 1, pos = 0; pos <= content.size(); pos += 4024, ++count)
{
string head = fileName + " :" + to_string(count) + "\n";
string splitMsg = head + content.substr(pos, 4024);
json contentJson = {{"content", splitMsg.c_str()}};
contentJson = {{"msgtype", "markdown"}, {"markdown", contentJson}};
jsonVec.emplace_back(contentJson);
}
}

问题解决 - 本地下载问题

wget -N 参数:如果本地文件​​不存在​​,它会直接下载该文件;如果本地文件​​已经存在​​,Wget 会向服务器发出一个 ​HEAD请求​​(而非完整的 GET请求)来获取该资源的​​最后修改时间​​ (Last-Modified头部)。

如果一个终端下载了此文件,然后在本地删除掉此文件,再尝试下载时,发现有时不会下载,即误认为存在一样的文件。

需要和后台那边进行沟通,让其提供一个校验码接口,以便可以和本地对比。

先尝试解压,后下载

优化了一下处理逻辑,先尝试解压再进行下载,对于已经下载好的日志包,效果很明显,直接略去了不必要的下载。

和后台联调 - 压缩包检验码问题

问了后台那边网址包含不包含压缩包校验码,
如果不包含,那就把异常情况放在解压缩的环节上,在解压缩脚本上进行异常处理

C调用Shell

popen、system、fork+exec三者的区别、和异常处理,

其中system可以让父进程自动阻塞,避免了下载文件、解压缩的进程安全问题,省去了好多进程控制的代码。但是返回值挺多的,得分好多情况,

popen是封装了fork、pipe、exec,自动关闭了不需要的读写端,由于封装了三个操作,可能代码上很方便,但是可能内部会出现一些异常,需要去避开坑点,

而fork+exec虽然很原始,但是让代码逻辑很明了,主进程可以在等待期间做一些自定义的事。

所以把代码中需要调用脚本的地方各取所需,分情况调用。这也给了一个启发,需要在调用时多看手册、多Google,明确细节和坑点。

日志分析系统总体流程

远程诊断新的需求

学习守护平台远程诊断日志上报模块有新的需求,昨天开发的是扫描局域网设备数的代码,需了解安卓多线程和异步编程的知识,学习service有关内容来更好的进行开发远程诊断模块。

前期主要做的是设备端的诊断代码实现,熟悉一下IoT的接口规范,和后台那边对接一下数据格式,熟悉一下传感器的知识,如何获取数据。

熟悉远程诊断现有的代码框架,在此基础上进行扩展,完成获取时间的代码,熟悉麦克风检测和获取传感器的代码。

代码完成后,和后台沟通数据模型,和后台进行联调。

完成网卡信息的获取代码,完成JSON的整合。自测之后,和后台那边进行联调,目前链路是通的,格式正确,但是有些值获取的有点小问题,比如子网掩码。

整理远程诊断的代码,提交到仓库。

调试了一下TC02和DT15的IoT远程诊断功能,解决了一些小问题,提交最新的代码等待合并。

Mac_终端配置

选择

Mac的终端有很多选择。
推荐得比较多的:

  1. iTerm2,是个老牌macOS终端,精巧。并且更新频繁。缺点是不跨平台。
  2. warp。rust写的。GPU渲染,看起来很现代。诟病比较多的是有时太占内存,甚至有时能吃2G。但是集成的无缝AI交互体验很好。
  3. Termius。是专门给多端使用的,主要用于管理SSH。用了用,感觉不太习惯。

终端配置

warp默认使用的是zsh配置文件。在/Users/mrcan/.zshrc
但zsh配置文件在macOS默认是没有的,需要手动创建。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# Warp Terminal & Zsh Configuration
# Colors for different file types in ls command

# Enable colors for ls on macOS
export CLICOLOR=1

# macOS BSD ls colors (LSCOLORS format)
# Format: directory:symlink:socket:pipe:executable:block:character:setuid:setgid:dir_w_sticky:dir_wo_sticky
export LSCOLORS=ExGxBxDxCxEgEdxbxgxcxd

# If you have GNU coreutils installed (brew install coreutils), uncomment these:
# alias ls='gls --color=auto'
# export LS_COLORS='di=1;34:ln=1;36:so=1;35:pi=1;33:ex=1;32:bd=1;34:cd=1;34:su=0;41:sg=0;46:tw=0;42:ow=0;43:mi=1;37;41:*.tar=1;31:*.tgz=1;31:*.zip=1;31:*.gz=1;31:*.bz2=1;31:*.xz=1;31:*.jpg=1;35:*.jpeg=1;35:*.png=1;35:*.gif=1;35:*.mp3=1;33:*.mp4=1;33:*.avi=1;33:*.mov=1;33:*.pdf=1;31:*.doc=1;31:*.txt=0;37:*.md=1;37:*.json=1;33:*.xml=1;33:*.yml=1;33:*.yaml=1;33:*.js=1;32:*.ts=1;32:*.py=1;32:*.go=1;32:*.rs=1;32:*.cpp=1;32:*.c=1;32:*.h=1;32'

# Useful aliases for colorful output
alias ll='ls -la'
alias la='ls -A'
alias l='ls -CF'

# Enable color support for grep
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'

# Git colors (if you use git)
alias git='git --no-pager'

# Warp works great with these modern alternatives (install via brew if desired):
# brew install exa && alias ls='exa --color=always --icons'
# brew install lsd && alias ls='lsd --color=always'
# brew install bat && alias cat='bat --style=auto'

以上配置文件的效果:
What’s now working:
• Colored directories - Blue folders
• Colored file types - Different colors for executables, links, etc.
• Useful aliases - ll, la, l for different listing views
• Colored grep - Search results will be highlighted

写入配置文件后,还需要source ~/.zshrc使这个配置文件立即生效。

macOS使用brew安装开发工具,以安装git为例

通常在macOS上有两种常用的安装方式:brew install或者xcode-select --install
xcode-select and brew, which is better? what are the difference of them

两者的对比

Here are the key differences between installing Git via xcode-select and Homebrew:

Xcode Command Line Tools (xcode-select --install)

Pros:

  • Apple-maintained: Official Apple distribution, well-integrated with macOS
  • Comes with essential dev tools: Includes GCC, make, and other development utilities
  • System-level installation: Installed in /usr/bin/git
  • No additional dependencies: Built into macOS
  • Required for many dev tasks anyway: Needed for compiling software from source

Cons:

  • Slower updates: Git version updates only come with macOS/Xcode updates
  • Older versions: Often ships with older Git versions
  • Less control: Can’t easily switch versions or customize installation

Homebrew (brew install git)

Pros:

  • Latest versions: Usually has the most recent Git releases
  • Easy updates: brew upgrade git keeps you current
  • Version management: Can install multiple versions if needed
  • Package ecosystem: Access to thousands of other developer tools
  • Customizable: Various installation options and configurations

Cons:

  • Additional dependency: Requires Homebrew to be installed first
  • PATH management: Need to ensure Homebrew’s path comes before system paths
  • User-space installation: Installed in /opt/homebrew/bin/git (Apple Silicon) or /usr/local/bin/git (Intel)

Which is Better?

For most developers, Homebrew is better because:

  1. You get newer Git features and security fixes faster
  2. You’ll likely want Homebrew for other development tools anyway
  3. Easy to keep everything updated

Use Xcode Command Line Tools if:

  • You prefer minimal system modifications
  • You don’t need the latest Git features
  • You’re doing iOS/Mac development (you’ll need Xcode tools anyway)

Recommendation: Install Xcode Command Line Tools first (many things depend on it), then install Git via Homebrew for the best of both worlds.

brew的安装

默认macOS是没有brew的。需要先安装。而安装brew还需要安装xcode command line tools(在安装brew时如果检测到没有这个,会自动帮你装)。

1
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

安装完之后,它会提示你,加入PATH:

1
2
3
4
# Run these commands in your terminal to add Homebrew to your PATH:
echo >> /Users/mrcan/.zprofile
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/mrcan/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"

之后,就可以brew help测试了。

但是,这里有个坑,就是第二句,实际最后.zprofile文件中保存成了eval \"$(/opt/homebrew/bin/brew shellenv)\"
导致下一次打开终端报错:

1
(eval):1: no such file or directory: export HOMEBREW_PREFIX=/opt/homebrew; export HOMEBREW_CELLAR=/opt/homebrew/Cellar; export HOMEBREW_REPOSITORY=/opt/homebrew; fpath[1,0]=/opt/homebrew/share/zsh/site-functions; PATH=/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin; export PATH; [ -z  ] || export MANPATH=:; export INFOPATH=/opt/homebrew/share/info:;

应该存成eval "$(/opt/homebrew/bin/brew shellenv)"才对。
修改之后,source ~/.zprofile即可生效。
The issue was in your .zprofile file where the quotes around the eval command were escaped (with backslashes), which caused the shell to interpret them incorrectly.
This command properly sets up your Homebrew environment variables (like HOMEBREW_PREFIX, PATH, etc.) that you saw in the error message. The error occurred because the shell couldn’t properly execute the command due to the escaped quotes.
Your shell should now work properly without that error. You can restart your terminal or run source ~/.zprofile to apply the changes.

brew安装git

1
2
brew install git
git --version

git配置

生成公钥

1
ssh-keygen -t ed25519 -C "your_email@example.com"

默认生成到了~/.ssh/id_rsaor~/.ssh/id_ed25519

实际测试,默认保存到了/Users/mrcan/.ssh/id_ed25519,这是私钥,公钥保存到了/Users/mrcan/.ssh/id_ed25519.pub

之后,把公钥上传到GitHub即可。

发现不能读取repo

1
ssh -T git@github.com

这是通用的检测方法。发现不行。
原因是我们没有把github.com添加到可信名单中。

1
ssh-keyscan -H github.com >> ~/.ssh/known_hosts

现在,再次

1
ssh -T git@github.com

回复:

1
Hi xing-cg! You've successfully authenticated, but GitHub does not provide shell access.

现在还需要在本地配置自己的user.email

1
git config --global user.email "myemail@xxx.com"

现在就可以正常git管理repo了。

安装npm

macOS默认没有npm。
可以用brew安装node.js。

1
2
brew install node
node --version

之后,在有package.json的目录中,就可以直接npm install安装依赖了。

hexo博客依赖安装

hexo博客目录下只npm install还不够,还需要安装hexo-cli

1
npm install -g hexo-cli

远程连接云服务器

1
ssh-keyscan -H mrcan.work >> ~/.ssh/known_hosts

之后才能进行连接请求:

1
ssh root@mrcan.work