前言: 出于某些原因, 要对 APP 沙盒数据进行实时监控. 但手动用 AK 的文件查看器操作太繁琐, 于是尝试用脚本来实现自动化监控以提高效率. 通过对脚本的优化, 倒逼自己不断地学习和总结 shell 编程知识.
update:2018-09-13 16:07:30
任务描述
实时查看安卓手机中
/data/data / 当前运行 APP 的包名 / files/
目录中以 jar 和 dex 结尾的文件名.
代码
- # V0.1
- while true;
- pkgname=$(dumpsys activity top|grep pid|awk '{print $2}'|awk -F '/' '{print $1}');
- do echo -n "#=============Checking $pkgname";
- date;
- find /data/data/$pkgname/ -iname \*.jar -o -iname \*.dex;
- sleep 1;
- done;
由于 busybox 为阉割版, 对换行后的脚本支持不到位. 代码本身没有换行, 为了便于观看, 这里做了换行处理.
代码解析
运行环境
Android 底层采用了 linux 内核, 可以执行一些基本的 shell 命令. 安装 busybox 后, 可以使用一些高级的命令.
初始配置
上述代码保存为 checknow.sh
发送到手机
adb push checknow.sh /data/local/tmp/
赋予执行权限
adb shell su -c chmod 0755 /data/local/tmp/checknow.sh
执行脚本
adb shell su -c /data/local/tmp/checknow.sh
在 shell 脚本中实现循环
要做到实时监控, 必须要有一个循环的逻辑. linux 系统中使用
watch -n 秒数 命令
可以每隔 n 秒执行一次指定命令, 但在手机中却运行不起来, 又是 busybox 的锅......
顺手学了一下循环指令:
- while true;
- do xxx;
- sleep n; # n 是秒数, 可以是小数.
- done;
获取当前运行的 app 信息
- shell@hammerhead:/ $ dumpsys activity top
- TASK com.miui.mihome2 id=1
- ACTIVITY com.miui.mihome2/com.android.launcher2.Launcher 43045638 pid=1107
- Local Activity 427982f0 State:
- mResumed=true mStopped=false mFinished=false
- mLoadersStarted=true
- mChangingConfigurations=false
- mCurrentConfig={0.85 460mcc65535mnc zh_CN ldltr sw360dp w360dp h567dp 480dpi nrml port finger -keyb/v/h -nav/h s.38}
- FragmentManager misc state:
- mActivity=com.android.launcher2.Launcher@427982f0
- mContainer=android.app.Activity$1@427a2640
- #......
在 adb shell 中, 通过 dumpsys activity top 可以获取手机屏幕上运行的应用信息. 但信息太多, 接下来可以用一系列的 shell 命令把 APP 包名给提取出来.
使用 grep 指令提取目标字符串所在行
- shell@hammerhead:/ $ dumpsys activity top|grep pid
- ACTIVITY com.miui.mihome2/com.android.launcher2.Launcher 43045638 pid=1107
在上面代码中,| 为管道命令, 将结果重定向到 grep 中. grep 后面跟一个关键词, 可以提取出关键词所在的一整行. 经过观察发现, pid 可以作为该关键词. 此外, grep -v 关键词可以查找不含关键词的行.
使用 awk 提取行中的关键词
- shell@hammerhead:/ $ dumpsys activity top|grep pid|awk '{print $2}'
- com.miui.mihome2/com.android.launcher2.Launcher
默认情况下, awk 会按照空格对行进行分割, 分割后可 '{print $ 数字}'按照位置顺序输出, 从 1 开始计数. 注意,'{print $0}'代表的是分割前的完整字符串.
接下来用 awk -F 对指定字符串 / 进行分割, 获取到包名 com.miui.mihome2
awk 支持正则, 也许不用多次使用 awk 分割, 以后若掌握了更高级用法会补充进来.
使用 shell 变量
将上述命令获取到的包名赋值给 pkgname, 供后续使用:
pkgname=$(dumpsys activity top|grep pid|awk '{print $2}'|awk -F '/' '{print $1}')
变量赋值: 变量名 =$(一条指令), 或变量名 ="字符串", 注意这里是圆括号.
变量引用:$ 变量名, 或 ${变量名}, 注意这里是花括号.
关于 shell 数组还可以参考这里 http://www.runoob.com/linux/linux-shell-array.html
使用 find 查找文件
find 命令可以递归查找指定文件夹内的文件, 基本用法为: find 目录名 -name 文件名.
来源: http://www.jianshu.com/p/584ac6776f9f