关于shell脚本的文章,教程很多。但是一般属于工具书类型的,遇到不清楚的再去查。
这里通过阅读Android的刷机脚本flash-all.sh
来学习实际当中的shell是怎么写的。
flash-all.sh脚本
我选择的是HiKey版本的刷机文件,在Master分支的device/linaro/hikey/installer
目录下可以找到。
原始文件只有72行,所以这里加上我的注释都贴出来了
#!/bin/bash
# $# - 输入参数的个数
# -eq - 与=类似,都是判断两个操作对象是否相同,但是前者针对整数,后者是字符串和数字都适用
# 这个判断是:输入的参数个数是否为0,即有没有输入参数
if [ $# -eq 0 ]
then
echo "Provide the right /dev/ttyUSBX specific to recovery device"
exit # 退出shell
fi
# -e - 判断文件是否存在
# $1 - 第1个输入的参数
# 这个判断是:第1个参数指定的文件不存在
if [ ! -e "${1}" ]
then
echo "device: ${1} does not exist"
exit
fi
DEVICE_PORT="${1}"
PTABLE=ptable-aosp-8g.img
# 如何输入的参数个数大于1,并且第2个参数为"4g",那么PTABLE变量为"ptable-aosp-4g.img"
if [ $# -gt 1 ]
then
if [ "${2}" == '4g' ]
then
PTABLE=ptable-aosp-4g.img
fi
fi
# 返回当前shell脚本所在的路径
INSTALLER_DIR="`dirname ${0}`"
FIRMWARE_DIR="${INSTALLER_DIR}"
# for cases that not run "lunch hikey-userdebu"
# -z - 变量的长度是否为0,即是否定义了变量${ANDROID_BUILD_TOP}
# 如果没有定义,则以当前目录为基准进行变量赋值
if [ -z "${ANDROID_BUILD_TOP}" ]; then
ANDROID_BUILD_TOP=${INSTALLER_DIR}/../../../../
ANDROID_PRODUCT_OUT="${ANDROID_BUILD_TOP}/out/target/product/hikey"
fi
# 如果${DIST_DIR}没有赋值,那么赋值
if [ -z "${DIST_DIR}" ]; then
DIST_DIR="${ANDROID_BUILD_TOP}"/out/dist
fi
#get out directory path
# 如果参数大于1个,那么遍历
# 从代码可以发现当前脚本支持2个参数:
# --out 值是自定义各个img的目录
# --use-compiled-binaries 如果有这个参数,表示使用编译生成的firmware
while [ $# -ne 0 ]; do
case "${1}" in
--out) OUT_IMGDIR=${2};shift;; # ";"表示连续命令, ";;"表示本次循环结束,相当于高级语言中的continue
--use-compiled-binaries) FIRMWARE_DIR="${DIST_DIR}";shift;;
esac
shift # shift表示移除第1个参数,即原来的第3个参数变成第2个参数,以此类推
done # 完成while循环
# 如果${FIRMWARE_DIR}是编译的目录,判断该目录下fip.bin与l-loader.bin是否存在
if [[ "${FIRMWARE_DIR}" == "${DIST_DIR}" && ! -e "${DIST_DIR}"/fip.bin && ! -e "${DIST_DIR}"/l-loader.bin ]]; then
echo "No binaries found at ${DIST_DIR}. Please build the bootloader first"
exit
fi
# 如果${OUT_IMGDIR}没有定义,那么使用${ANDROID_PRODUCT_OUT}作为其值
if [ -z "${OUT_IMGDIR}" ]; then
if [ ! -z "${ANDROID_PRODUCT_OUT}" ]; then
OUT_IMGDIR="${ANDROID_PRODUCT_OUT}"
fi
fi
# 如果${OUT_IMGDIR}不存在
if [ ! -d "${OUT_IMGDIR}" ]; then
echo "error in locating out directory, check if it exist"
exit
fi
echo "android out dir:${OUT_IMGDIR}"
# 原本以为"烧写环境没有进行",但是看了代码才发现,这一步也进行了
# 可参考:http://wiki.lemaker.org/HiKey(LeMaker_version):Quick_Start
sudo python "${INSTALLER_DIR}"/hisi-idt.py --img1="${FIRMWARE_DIR}"/l-loader.bin -d "${DEVICE_PORT}"
# set a unique serial number --- 对serialno这个参数不熟悉,之前没见过
fastboot oem serialno
fastboot flash ptable "${INSTALLER_DIR}"/"${PTABLE}"
fastboot flash fastboot "${FIRMWARE_DIR}"/fip.bin
fastboot flash nvme "${INSTALLER_DIR}"/nvme.img
fastboot flash boot "${OUT_IMGDIR}"/boot.img
fastboot flash system "${OUT_IMGDIR}"/system.img
fastboot flash cache "${OUT_IMGDIR}"/cache.img
fastboot flash userdata "${OUT_IMGDIR}"/userdata.img
以上中文部分都是我的注释
从代码可以发现当前脚本支持2个参数:
–out, 值是自定义各个img的目录
–use-compiled-binaries 如果有这个参数,表示使用编译生成的firmware
脚本中用到的指令
$#
输入参数的个数
-eq与==的区别
两者都是用来判断两个操作对象是否相同,前者只适用于整数,而后者支持数字与字符串
-gt
大于
INSTALLER_DIR=”`dirname ${0}`”
计算表达式dirname ${0}
的值,将其赋值给INSTALLER_DIR
-z与-n
-z是变量的字符串长度是否为0
-n是变量的字符串长度不为0
-d
目录是否存在
-e
文件是否存在
;与;;
;表示连续命令
;;表示本次循环结束,相当于高级语言中的continue
-ne
与-eq
相反,不等于
shift
常用于case中,表示移除第1个参数,即原来的第3个参数变成第2个参数,以此类推
有意思的if与case
这两个的语法比较有意思,结束标记是原来的字符串反过来写,即fi
和esac
这里列出来的语法非常有限,碰到不清楚的,大家可以自行查询
参考
- shell语法简介
- linux shell 判断变量是否为空。-n -z 有什么不同呢?
- Shell编程中Shift的用法
- shell 基础 $(cd dirname $0;pwd)
- linux中shell变量#,@,0,1,$2的含义解释
- Bash shell 中 “-eq” 与 “=” 等价吗?