2019-04-19
关键字:Android机顶盒常用命令、Linux命令
笔者早年间从事 Android 机顶盒开发工作,那会刚毕业,技术也比较菜,工作过程中遇到过不少困难,不过所幸当时就有做笔记的习惯,很多工作过程中遇到的问题或者一些 “奇淫技巧” 都被我记录了下来。最近学到一个新词:复盘。恰好这段时间也在复盘自己之前的工作,发现自己虽然很长一段时间不碰机顶盒了,但之前积累下来的笔记还真不少。笔者不太甘心让这些 “年少的自己” 就这样尘封在暗无天日的笔记本里,加上一时间整理癖发作,就打算将它们整理成文发表出来,希望能帮到一部分后生们。
这篇文章记载的是笔者在 Android 机顶盒开发过程中经常用到的一些命令。
本篇文章提及的常用命令按 Linux 、 Android 以及 Git 三个部分来讲。这些命令基本就支撑起了笔者全部的机顶盒开发过程。
1、Linux
2、Android
3、Git
1、Linux
这里的 Linux 命令有分服务器版及机顶盒版。因为机顶盒上的 Linux 系统被删减了很多功能,因此,有些命令或参数并不适用于机顶盒。
find
find .
遍历当前目录。将当前目录及其子目录下的所有文件都列出来。
find -name init.rc find -name "init*"
首先是两条最基本的命令,查找某文件的位置。如果要查找的文件名含有通配符,最好加上双引号。
find -type d -name "etc*" find -type f -name "etc*"
这个是按类型查找。 -type 参数后面接 d 表示只查找目录名,接 f 表示只查找文件名。
find /system -type f -name "ppp*"
这条命令是指定目录查找。要指定目录时,目录名一定要放在最前面。
上面 4 条就是机顶盒和 Linux 服务器上通用的 find 命令了。需要注意的是机顶盒不支持直接 find ,需要通过在普通 find 命令前加上 busybox 来执行。busybox 是一个工具程序,它位于 /system/bin/busybox , 有些平台 busybox 会直接链到 /system/bin/toolbox 上。
下面几条则是只在 Linux 服务器上才支持的 find 命令了。
find -maxdepth 2 -type f -name "*.mk"
设置目录查找深度查找。这条命令表示只查找当前目录及一级子目录下的 .mk 文件。
find vendor/ -size +2M find system/ -size +1024k find device/ -size -20c
这几条命令是按文件大小来查找。分别是查找大于 2M 的文件、查找大于 1024KB 的文件、查找小于 20 个字节的文件。
find vendor/ -size +2M -exec ls -alh {} \; find vendor/ -size +2M | xargs ls -alh
find vendor/ -size +20M | xargs rm -rf
前面两条命令的执行结果是等效的。效果是将前面查找到的结果应用一下 ls -alh 命令。第 3 条命令也比较常用,查找某类文件并将它们删除。下面那种 | xargs 格式的命令并不支持接所有指令。如果遇到不支持接的,换成第 1 种格式就可以了。
grep
grep -nr "ttyUSB" vendor/ grep -i "ttyUSB" vendor/ grep -A 5 -B 3 "ril" device/
这几条 grep 命令撑起了我的日常工作。
第 1 条是我最常用的 grep 命令,表示在 vendor 目录下查找包含 ttyUSB 字符串的文件,并将它们的文件名称以及所在行数列出来。
第 2 条的 -i 参数表未忽略大小写查找。
第 3 条表示匹配到结果以后,再往前多显示 5 条,往后多显示 3 条。
操作目录
pwd pwd -L pwd -P
查看当前目录的绝对路径。前面两条命令的效果是一样的,将会显示当前目录的绝对路径。 第 3 条命令显示的是当前目录的真实路径,与上一条的区别就是对待 “软链接” 的显示方式了。如果当前目录下有软链接,加 -P 参数会显示出该软链接链向的实际路径。
mkdir /system/myf0
mkdir -p /system/myf1/myf2
创建目录。加个 -p 参数表示递归创建目录,否则的话,只能在已存在的目录上创建目录。
空间统计
du -ah du -sh du -d 1 -ah
du -d 1 -ah /usr/local
统计当前目录的空间占用情况。
第 1 条命令将会递归查找文件与目录,列出每个目录及文件的大小。参数 a 表示所有文件,参数 h 表示以适宜阅读的形式表示其大小,如多少 KB ,多少 MB 。
第 2 条命令也是递归统计当前目录所占的空间大小,只不过它不会列出每一个文件与目录的占用情况,而是只列出一个总的结果值。
第 3 条命令则是递归统计当前目录所占的空间大小,只列出当前目录下各一级目录的的占用空间情况,并列出当前目录占用空间总情况。
第 4 条命令则是指定一个目录来统计。
df -h
列出当前文件系统磁盘空间占用情况,实际作用不大,但闲着没事时就喜欢敲敲它。
解压缩
tar -zcvf 目录 输出名称.tar.gz
tar -zcvf 目录 | split ‐d ‐b 50m 输出名称.tar.gz
以 tar.gz 格式压缩。第 2 条指令是分卷压缩,每 50MB 分一个文件。
tar -zxvf 文件名称.tar.gz
tar -zxvf 文件名称.tar.gz -C 输出目录
解压。对于分卷压缩的文件,可以将它们合并成一个文件。
cat 分卷压缩文件.tar.gz.a* > 输出名称.tar.gz
Linux 的分卷压缩最后面一般都是以 aa, ab, ac 等命名的。
至于 ZIP 格式的压缩,就不说了,笔者用的比较少。
更改权限
chmod 755 /system/bin/rild chown root:customer /system/etc/ppp/chat chgrp customer /system/bin/rild
chmod 命令用的还比较多一点。其它的,用的就很少了。Android 系统对文件权限要求比较严格,对某些系统关键文件稍微有点权限不对,编译出来的系统都用不了。所以一般很少主动更改文件权限的。
计算 MD5
md5 /system/bin/sh
md5sum /system/bin/rild
求 MD5 值还算是比较常用的,在比对是否推错程序时很有用处。不过不同的设备集成的 md5 计算工具可能不一样,甚至有些系统没有集成计算 md5 的工具。所以上面的命令其实不具备代表性。
查看进程
ps
查看系统当前进程。机顶盒开发过程中很常用的命令。
top top -d 1
查看当前系统进程及其资源占用情况。直接一个 top 是每 3 秒更新一次。加个参数 -d 1 则是每秒更新一次值。
dumpsys activity | grep Focus dumpsys activity | grep ocu
dumpsys activity -f | grep ocu
这条命令在机顶盒端也很常用,用来查询当前处于栈顶的 Activity 名称。上面两条命令完全是一样的,只不过笔者本人嫌第 1 条指令要按一个大写的 F 麻烦,所以一般会用第 2 条,会顺手很多。第 3 条是在当前活动栈中查找,其实效果都一样。
系统属性
这个是针对机顶盒的。
getprop ro.adb.secure getprop | grep "ril" setprop service.bootanimation.exit 1
分别是获取属性和设置属性。
命令行输入遥控器按键
input keyevent KEYCODE_DPAD_CENTER input keyevent 23
也比较常用的命令。可以将这些指令封装成脚本文件来做压力测试。
ADB
ADB 命令推文件调试非常常用啊有木有。
用这个必须要确保 adbd 进程正在运行当中,可以 ps | grep adbd 查看一下。一般默认的 adbd 端口是 5555 ,当然,有些项目为了所谓的安全,会改端口号,一般可以 getprop | grep port 查看一下。对了,好像还要确认一下 ro.adb.secure 属性的值。在这一切前提条件都满足以后,就可以开始使用 adb 连接了。
adb connect 192.168.x.x adb connect 192.168.x.x:17173 adb remount adb devices adb disconnect adb disconnect 192.168.x.x adb push from/file.name /to/file.name adb pull from/file.name
一般比较常用的就这些了,就不逐条解释命令了。 adb pull 命令拉取上来的文件默认是存在电脑的用户目录根目录下的。win 10 系统貌似不能指定存储路径。
KILL
kill 1476 kill -9 51
根据 PID 杀进程。 -9 参数把它理解成杀死一个顽固进程,哈哈。
busybox
busybox 是一个应用程序。在海思平台中,busybox 程序通常是软链接到 /system/bin/toolbox 程序上的。busybox 是一个工具集,它提供的功能有很多,但常用的却不多。
busybox ifconfig busybox ifconfig -a
上面两条命令一般用来查看机顶盒中的网卡信息。 -a 参数是列出所有网卡信息,包括未启用的。
busybox ifconfig eth0 hw ether 0c:c6:55:83:24:75
临时修改 eth0 网卡的 MAC 地址。
busybox dmesg -n 1 echo 1 > /proc/sys/kernel/printk
关闭内核打印,上面两条命令的效果是一样的。
编译
通常 Android 系统的编译都离不开下面几条命令
source build/envsetup.sh lunch xxx
这两步是准备编译链环境。
make otapackage -j32 make bigfish -j32 mm mmm vendor/xxx/app/MyApk/
这几条就是编译命令了。
前面两条是编译大包的命令,不同平台会有不同编译参数。第 1 条是 Android 原生编译参数,第 2 条是海思平台的编译方式。
mm 命令是编译当前目录用的,需要当前目录下有 Android.mk 文件才行。
mmm 命令则是指定目录编译,同样的也需要指定的目录下有 Android.mk 文件才行。
额外提一下,这个 mm , mmm 命令都是在 ./build/envsetup.sh 脚本中定义的函数。
通过命令恢复出厂设置
下面介绍的是海思平台通过命令恢复出厂设置的方式
1. 在 /cache 目录下创建 recovery 目录 2. echo --wipe_data > /cache/recovery/command 3. echo boot-recovery > /dev/block/platform/hi_mci.1/by-name/misc 4. sync 5. reboot
上述第 3 步可能会随着版本的不同,某些目录名称可能会有变动,灵活应用即可。
APK 手动签名
严格来讲,这并不算是命令。但因为也比较常用,还是简单提一下吧。
将 signapk.jar 文件拷贝至签名密钥所在的目录。
./out/host/linux-x86/framework/signapk.jar
签名密钥文件不同平台的存放目录不一样,您可以搜索看看 platform.x509.pem 文件存储于哪个目录就将 signapk.jar 文件拷贝至哪个目录。
上面步骤都准备好后,就可以通过以下命令给 APK 签名了。事先进入到存放了签名密钥的目录。
java -jar signapk.jar platform.x509.pem platform.pk8 XXX.apk XXX_signed.apk
抓日志
Android 的日志分为好几个级别。main, system, radio, events 等。
logcat -s 标签名称 logcat *:E logcat -c;logcat logcat > /data/mine.log logcat -v process | grep 1471 logcat -v time -s 标签名称
抓取 main 级别日志。倒数第 2 条是按进程号过滤日志。最后一条是显示日志的时间戳。也可以通过 telnetd 来远程抓取日志,不过用的非常少,而且很多机顶盒没有预置 telnetd 程序,所以就不说了。
logcat -b radio logcat -b logcat -c -b radio
抓取 radio 级别的日志。最后一条是清除 radio 级别的日志。
抓网络包
tcpdump -i eth0 -s0 -w /data/player.pcap
有些机顶盒没有预置 tcpdump 程序的。
2、Android
这一章节主要介绍下操作四大组件的常用命令。
pm
pm install demo.apk pm uninstall com.your.pkg pm -l
pm 命令里比较常用的就这几条了。
前面两条是安装和卸载 APK 的命令。
第 3 条是列出当前安装的所有 APK 包名及其 APK 位置。笔者通常用这条命令配合 grep 来查找某 APK 的安装信息。
Activity
am start com.chorm.four
am start com.chorm.four/.MainActivity
启动 APK 。其中第 1 条命令要求主 Activity 的注册 category 属性中有 “ android.intent.category.DEFAULT ” 。 第 2 条命令则没有这个要求,通常用第 2 条命令启动 APK 比较多。不过还是比较经常出现上面两条都启动不了的情况。这个时候就要借助另一条无敌指令来帮忙了。
monkey -p com.chorm.four 1
monkey 据说是一个测试工具,不过不管,笔者只用它来帮忙启动一些 APK 。monkey -p 是固定参数,后面接个 APK 包名,最后一个数字填个 1 就好了。据说这个工具的设计目的就是想模仿一只猴子,胡乱地去操作我们的 APK ,进而测试 APK 的稳定性等。最后面的数字参数就是想要让这只猴子胡乱操作的次数。
Broadcast
am broadcast -a my.broadcast.action
通过命令发送一条全局广播。 -a 参数后接的是广播 Action 名。
Service
am startservice com.chorm.four/.MyService
通过串口启动 Service 。
ContentProvider
content query --uri content://stbconfig/authentication content insert --uri content://settings/global --bind name:s:chormname --bind value:s:lemontea content update --uri content://settings/global --bind value:s:hello_xiao_tea --where "name=\'chormname\'" content delete --uri content://settings/global --where "name=\'chormname\'"
ContentProvider 的 CRUD 命令全在这了。其实没什么,记住这些命令就好了,实在记不住,在串口敲一下 content 命令就会出来简明帮助信息了。
这里可以关注一下上面标红的字体。三段式结构是固定的。因为 ContentProvider 是以 key-value 对的方式存储数据的, name 就代表 key 了,第 2 段 s 表示我们以字符串的形式来匹配字段。 后面的 value:s:xx 也一样了。 中间的 s 字段还有其它几种类型,可选的类型有如下几种
b - boolean, s - string, i - integer, l - long, f - float, d - double
其实这些东西,在串口上敲一下 content 命令都会出来帮助信息。
3、Git
笔者在公司使用的代码管理工具一直都是 Git ,而且笔者认为 Git 比 SVN 更有优势。
建仓
git config --global user.name your.name git config --global user.email you@email.com
在首次使用 Git 工具时,需要先设置一下这些信息才能正常使用 Git 的功能。
git init
初始化代码仓库,在当前目录下初始化一个 .git 目录,并开始跟踪当前目录及其子目录。
git remote add origin git@192.168... git remote -v
第 1 条是为当前 Git 添加一个远程仓库。第 2 条则是查看当前 Git 仓库的远程仓库信息。
git push -u origin master
在添加好远程仓库信息后,即可以将本地仓库推送到远程仓库了。
不过一般而言,建仓流程都是首先建立远程代码仓库,然后再由我们的机器主动去克隆代码的。
git clone git@192.168... git clone git@192.168... -b master2 git clone git@192.168... -b master2 myfolder/ git clone --depth 3 git@192.168... -b master2 myfolder/
将远程仓库中的代码克隆到本地来。
第 1 条是默认克隆,完整克隆代码仓库,并切换到 master 分支。
第 2 条也是完整克隆,只不过克隆完后会自动切换到指定的 master2 分支。
第 3 条和第 2 条一样,只是会克隆到指定的目录中去。
第 4 条是部分克隆,它只会克隆指定的 master2 分支到指定的 myfolder 目录,并且只会克隆最新 3 条记录。这种克隆方式对于一些庞大的代码仓库来讲,能大大减少空间占用量,因为它只克隆最近的几条记录,并且这种克隆方式不支持分支切换,所以必须要在克隆前就指定好你想要哪个分支。
其实在工作过程中,建仓这种事,我们软件开发很少去操心的。
代码管理
git status
git status vendor/
与当前机器上最新的版本对比,列出有修改的文件。第 1 条命令是列出整个 Git 仓库的变化。第 2 条命令则是只看指定的 vendor 目录的变化文件。
git diff xxx.xxx
查看指定的文件的详细变化情况,可以接多个文件参数。
git add file.name git add .
添加有修改的文件到待提交区。第 1 条命令是添加指定的文件。第 2 条指令是添加所有有变化的文件到待提交区。
git commit -m "Some description"
将待提交区的代码提交上去,并以 -m 参数后的内容作为描述内容生成一条新的 Git 记录。
git push
将当前新提交的 Git 修改记录更新到远程仓库中去。
git pull
git pull origin branch2
从远程代码仓库中下载新记录。第 1 条是更新所有分支。第 2 条则是从 origin 源中更新指定的分支。
git log
git reflog
git log --graph
git log -1
git log --stat
查看提交记录。
第 1 条是按时间倒序查看所有提交记录,是最常用的 log 命令。
第 2 条则是查看在本机中的所有操作记录。
第 3 条可以以图形的形式查看所有人对分支的提交 / 合并情况。用的比较少。
第 4 条查看最近 1 条提交记录。
第 5 条查看每条记录都修改了哪些文件。
git rm file.name
取消跟踪指定的 file.name 文件。
git clean -df
强制删除所有未跟踪且未在忽略列表中的文件。
代码控制
git reset --hard HAED
git reset file.name
git reset 要回退的版本号 file.name
git reset --hard 版本号
第 1 条命令,强制让代码恢复到当前最新记录。该操作会放弃所有对文件的修改。
第 2 条命令通常用于已经将某文件提交到 “待提交区” 的情况,对这种情况的文件执行这条命令,会使指定的文件回退到 “已修改” 的状态。
第 3 条命令则是对 “已提交” 的文件进行回退,回退到指定的版本。这种情况其实是新生成一条记录提交上去。
第 4 条命令是强制让代码整体回退到指定的版本号记录上。
git checkout file.name
将指定文件的修改回退到未修改前的状态。这条命令只对已发生修改,但尚未添加到 “待提交区” 的文件有效。
分支操作
git remote rm origin branch1
删除远程仓库上的指定的 branch1 分支。
git branch git branch -a git branch branch0
查看分支情况。
第 1 条是查看本地已有的分支情况。
第 2 条是查看本地及远程仓库中所有的分支情况。
第 3 条是在本地新建一条分支 branch0 。
git checkout branch2
git checkout -b branch3
切换分支。
第 1 条是切换到指定的 branch2 分支。
第 2 条是新建分支 branch3 并切换过去。
git cherry-pick 记录版本号
将指定版本号的记录修改合并到当前分支来。
删除一条已存在分支的实例
假设我们要删除一条已有记录的分支,可以按如下步骤来做。
1. 首先找到这条要删除的分支名称;
git branch
2. 删除这条分支在本地的记录;
git branch --delete branch_name
3. 删除在本地保存的远程分支信息;
git branch -r --delete origin/branch_name
4. 删除在远程服务器上的分支信息;
git push origin --delete branch_name
当然,在一般的工作过程中,分支信息是只能增不能删的。
其它
git config --add core.filemode false
执行这条配置信息后,会使我们本地的 Git 忽略掉文件模式的变化。
git config --global core.quotepath false
解决中文乱码的问题。
git config --global core.autocrlf false
解决 Windows 与 Linux 系统换行符不同的问题,是否会自动将这些不同的换行符作转换。
git config --global http.proxy="http://192.168.100.252:38098"
设置网络代理。
忽略已跟踪文件的后续修改
在工作过程中,经常会碰到这样的一种需求:某些文件是必须要提交到 Git 去管理的,但这些文件可能会在工作过程中被自动修改,而我们又不想将这些修改提交上去。所以我们可以这样做
git update-index --assume-unchanged file.name git update-index --no-assume-unchanged file.name
这两条命令分别是对 file.name 文件的忽略跟踪后续修改以及恢复跟踪后续修改。
如果想看看当前有哪些文件是被忽略跟踪后续修改的,可以用下面这条命令
git ls-files -v
git grep "xxx"
对了,有时候我们可能需要 grep 整个大包目录,为了减少一些 grep 工作量,可以用这条命令来代替。效果是一样的。