shell脚本实现开机时间统计

1. 场景:需要多次数统计Android的开机时间

在移植完汇编解释执行后,需要对比c++的解释执行和汇编解释执行这两种情况下的开机时间。一开始采用的比较土的自己掐秒表方法,但一方面需要统计的次数比较多,另一方面自己掐秒表太费时也太耗精力,如何使用shell脚本实现自己开机,统计。

首先通过查询,android启动成功的标志为Android字样出现,在riscv汇编解释执行的情况下在logcat中会生成I ActivityTaskManager: Displayed com.eswin.tv.launcher/.homepage.HomepageActivity:,本来想直接查看logcat中该字符串出现的时间,但是在log中时间参数会发生两次跳变,因此需要通过计算自身pc的时间:从emulator启动到该字符串出现。

2. shell脚本需要注意的事项

  • shell脚本其实就是在linux终端中敲得命令集合生成的一个文件,相当于我们把所有敲得命令都放到一个文件中,执行这个文件就可以直接运行很多代码。这样做可以大幅度减少测试的时间,提高开发的效率。最简单的shell脚本就是把你要执行的文件复制到一个sh文件中,然后执行。
  • 在终端中创建一个shell脚本,此次创建的脚本名称为launch_time.sh,如果直接./launch_time.sh那么是无法执行的,需要先进行增加权限操作chmod +x launch_time.sh./launch_time.sh方可以执行。在一些情况下,不需要改变权限,通过source的方式可以直接运行脚本。但是在这次的测试的时候发现如果source launch_time.sh终端会直接挂掉,具体原因不得而知。
  • 在vscode中创建sh脚本文件最麻烦的一点就是没有命令的提示。这就导致在上下文中如果变量比较多,自己写就很容易写错。所以所有的变量不要手写,在定义一次之后就全部复制。比如我在写的时候就出现了这个问题:sum_time=$(($sumtime+$total_time))本意是实现sum_time每次运行之后加上total_time,但sumtimesum_time在这里被我搞混了。在计算机眼中,这是两个变量,这就导致自加失败,因为sumtime如果没有定义的情况下,默认为0
  • shell脚本和c语言不同之处在于,shell脚本不需要编译,而是直接运行,但是其语法与c又有相似之处。在shell脚本中,变量是不要定义的,可以直接使用比如pid=1
  • shell脚本对格式的要求是比较高的,很多地方必须要加上空格比如if [ -n "$pid" ];then-n前,“pid”后必须得有空格。在if和then之间需要加;,但是在if的实现中是不需要加;的。还有比如变量的定义pid=1等号两边是不能空格的,如果写成pid = 1就错了,这些在c语言中空格等不会影响程序。

#3、代码实现

function get_starttime(){
    starttime=$(date +%Y-%m-%d\ %H:%M:%S)
    # echo "start emulator: $starttime" | tee -a launch_time.txt
}
# function可以用来定义函数,其函数的定义格式和c比较像。
# 但是该函数没有返回值,如果调用该函数只不过是把这个函数中的代码进行移动。
# 如果定义的是函数,如果没有调用函数,该函数中的内容也不会执行。
# date指令可以实现打印时间,读者可以再终端中直接敲date命令,会显示出时间。
# %Y-%m-%d\ %H:%M:%S分别代表年月日,小时,分钟,秒:2021-03-25 17:00:22
#这个时间的格式也需要注意,因为接下来我们会用字符串出现的时间减去emulator开启的时间
# 所有变量的使用都要加上$ 不然默认的是字符串,比如pid=1,打印要变成echo $pid
function get_endtime(){
    endtime=$(date +%Y-%m-%d\ %H:%M:%S)
    # echo "end time:$endtime" | tee -a launch_time.txt
}
# 此处得到的是字符串出现的时间,在出现的时候获取pc的时间,如果需要查看该处的具体时间可以放开注释
# tee -a表示将内容添加到launch_time.txt中,如果没有-a,则是直接覆盖

function stop_adb(){
    pid=$(ps -a | grep adb | awk '{printf $1}');
    if [ -n "$pid" ]; then
        kill -9 $pid
    fi
}
# 由于我们是在emulator中,如果需要多次尝试开机关机,那么就需要多次开启adb,关闭adb
# 关闭adb的方法就是ps -a在开启的所有进程中grep寻找adb的进程
# awk '{printf $1}'的意思为截断输出的结果,并输出为第一列的值,如果为awk '{printf $3}'则是第三列的值
# 用kill -9来杀死对应的adb进程号
# 项目组前期使用的命令为:pid=$(netstat -anp | grep 5554|awk '{printf $7}'|cut -d/ -f1);我用我的理解进行了改进

function stop_emulator(){
    pid=$(ps -a | grep qemu | awk '{printf $1}');
    if [ -n "$pid" ]; then
        kill -9 $pid
    fi
}
# emulator为安卓模拟器,开启之后会有开机画面

function get_totaltime(){
    total_time=$(($(date -d "$endtime" +%s) - $(date -d "$starttime" +%s)))
    echo "NO.$num total time:$total_time s" | tee -a launch_time.txt
}
# 此处首先要注意函数的命名和变量的命名要区分开,不然在理解上容易出错,之前把函数名也定义成为了total_time
# date -d有比较强大的功能,后面跟上指令可以实现很多,比如:date -d tomorrow会输出明天的日期:2021年 03月 26日 星期五 17:07:18 CST
# 此处的作用加上了+%s,其作用是将时间转化成秒数,如果要算数运算,需要用上$(()),或者$[]

function launch_time(){
    stop_adb
    stop_emulator
# 为了阻止前一次的emulator没有关掉影响我们的启动,首先先确保一次emulator和adb关了
    emulator -no-cache &
# emulator -no-cache为启动模拟器,&为后台运行,因为接下来的操作相等于需要在另一个终端中运行
    get_starttime
# 启动之后获取此刻的pc时间
    adb wait-for-devive
# 等待emulator启动成功
    adb logcat > launch_time.log &
# 生成的log文档保存到 launch_time.log
    while true
        sleep 1
# 不停的循环去寻找成功开启的字符串,直到找到后退出while循环,sleep的原因是等log生成之后再去寻找,如果运行的太快launch_time.log中可能还没有东西
    do 
        if grep "I ActivityTaskManager: Displayed com.eswin.tv.launcher/.homepage.HomepageActivity:" launch_time.log; then
        get_endtime
# 找到字符串之后获取此刻的pc时间作为endtime
        get_totaltime
# 将两个时间转化成秒然后相减
        sum_time=$(($sum_time+$total_time))
# 需要统计开机的平均时间,所以先计算总时间
        stop_adb
        stop_emulator
# 本次时间计算完成,关闭模拟器和adb
        # rm launch_time.log 
        break
        fi 
    done
}

if(($1 > 0)) && (($1 < 21)) && (($2 > 0)); then
# $1为脚本的第一个入参,lunch的环境只有1~20,$2为第二个参数为需要测试的次数
    stop_adb
    stop_emulator
    source build/envsetup.sh
    lunch $1
    echo "lunch target: $1"
    rm launch_time.txt
    echo "Number of tests: $2"
    sum_time=0
# 将sum_time初始化为0,加下来循环执行开关机
    for((num=1;num<=$2;num++))
    do
    launch_time
    done 
    average_time=$(($sum_time/$2))
# 计算平均时间
    echo | tee -a launch_time.txt
    echo "$2 times in total"| tee -a launch_time.txt
    echo "avergae time: $average_time s" | tee -a launch_time.txt
else
    echo "please input right TARGET_PROTECT and Cycle boot times eg:./launch_time.sh 16 3"
    exit 8
fi 
#如果输入的情况不正确,shell退出

执行脚本,lunch的环境为riscv,在本机中为16,循环的次数为2:

./launch_time.sh 16 2

结果输出到launch_time.txt中:

NO.1 total time:157 s
NO.2 total time:162 s

2 times in total
avergae time: 159 s
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值