通过管道执行命令,获取各个命令的返回值

比如执行命令:cmd1 | cmd2 | cmd3 。 如果命令执行完后,通过”$?”获取的是cmd3的返回值。如何获取cmd1和cmd2的返回值呢?

在bash环境下,命令的返回值保存在”PIPESTATUS”数组中:

  • ${PIPESTATUS[0]} 是cmd1的返回值;
  • ${PIPESTATUS[1]} 是cmd2的返回值;
  • ${PIPESTATUS[2]} 是cmd3的返回值;
  • $? 始终等于 ${PIPESTATUS:-1}。

参考文章

阅读全文 »

查找
查找以ro.build.id=开头的行

1
awk '/^ro.build.id=/ {print $1}' build.prop   #在build.prop文件中查找

下面的例子实现了同样的效果,但是采用了变量的形式,用起来会更加灵活

1
2
prop_name=ro.build.id
awk -v identifier="${prop_name}=" '$0 ~ "^" identifier {print $1}' build.prop

分割字符
默认以空格为分隔符,比如:input | awk '{print \$1}'
可以通过-F参数指定分隔符,比如: input | awk -F "->" '{print $2}'

字符串替换

1
awk 'BEGIN { FS="SYSTEM/" } sub(/SYSTEM/,"system") {print $$2}'

实例:

1
zipinfo -1 target-V100R001C02B013SP06.zip | awk 'BEGIN { FS="SYSTEM/" } sub(/SYSTEM/,"system") {print $$2}'

查找SYSTEM/开头的字符串,并把SYSTEM替换为system后输出
或者:

阅读全文 »

内容替换

普通字符替换

1
2
param_name=ro.build.id
sed -i "s/${param_name}=.*/${param_name}=new_value/g" build.prop

本例用于修改build.prop文件中的ro.build.id参数的值

1
sed -i "s/oldstring/newstring/g" `grep oldstring -rl yourdir`

批量替换

二进制内容替换

1
sed -i 's/\x00/\x0a/g' %s      #本例是把'\0'替换为'\n'

行操作

删除文件中的某一行

阅读全文 »

死机问题在程序开发过程中是经常遇到的问题,本文介绍通过addr2line工具解析堆栈来定位死机问题

使用addr2line定位死机问题

在某个C应用程序挂掉后,会生成堆栈信息,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
F/libc    (21866): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1)
W/ (21866): [SkCanvas* DrawSurface::lockCanvas(const android::Rect&)]-----[76]
I/DEBUG ( 944): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG ( 944): Build fingerprint: 'full_godbox/godbox:4.0.3/8841C/84125002:eng/ test-keys'
I/DEBUG ( 944): pid: 21866, tid: 21866 >>> demo_cmd <<<
I/DEBUG ( 944): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000
I/DEBUG ( 944): r0 00000003 r1 00000000 r2 000010b0 r3 0000001f
I/DEBUG ( 944): r4 41334124 r5 00000000 r6 beae2f94 r7 00000046
I/DEBUG ( 944): r8 beae2f08 r9 00000010 10 00000bb8 fp beae3024
I/DEBUG ( 944): ip 400c6108 sp beae2f00 lr 41331d13 pc 41331d42 cpsr 00000030
I/DEBUG ( 944): d0 0000000000000000 d1 0000000000000000
I/DEBUG ( 944): d2 0000000000000000 d3 c1859800408ca000
I/DEBUG ( 944): d4 4125f000c1981600 d5 43ff000041200000
I/DEBUG ( 944): d6 0000000000000000 d7 0000000000000000
I/DEBUG ( 944): d8 0000000000000000 d9 0000000000000000
I/DEBUG ( 944): d10 0000000000000000 d11 0000000000000000
I/DEBUG ( 944): d12 0000000000000000 d13 0000000000000000
I/DEBUG ( 944): d14 0000000000000000 d15 0000000000000000
I/DEBUG ( 944): scr 60000010
I/DEBUG ( 944):
I/DEBUG ( 944): #00 pc 00002d42 /system/lib/libtest.so (std_ping)
I/DEBUG ( 944): #01 pc 0000f466 /system/bin/demo_cmd
I/DEBUG ( 944):
I/DEBUG ( 944): code around pc:

这种情况下就可以通过addr2line命令定位出死在了哪一行代码:

1
2
addr2line -e libtest.so 00002d42
addr2line -e demo_cmd 0000f466

注意:我们机顶盒上的so库或者可执行程序,一般都是被stripped的,是无法使用addr2line命令定位死机位置的。这种情况下,则需要找到对应的not stripped的同名文件。这两个文件必须是同一次编译生成的。
  可以使用file命令查看strip状态,如下:

1
2
3
4
$ file system/bin/demo_cmd
system/bin/demo_cmd: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), stripped
$ file symbols/system/bin/demo_cmd
symbols/system/bin/demo_cmd: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), not stripped

备注:

  • 本文介绍的所有命令,都是在Linux主机上执行的命令;
  • addr2line解析的文件必须是”not stripped“的文件。如果是android sdk,一般放在out的symbols目录下,比如:out/target/product/xxx/symbols/
  • 如果是Android机顶盒,应用程序挂掉后在/data/tombstones/目录下面会生成墓碑文件tombstone_*。在这些文件中就会有堆栈信息。
阅读全文 »

java代码中打印堆栈

Java代码打印堆栈比较简单, 堆栈信息获取和输出,都可以通过Throwable类的方法实现。目前通用的做法是在java进程出现需要注意的异常时,打印堆栈,然后再决定退出或挽救。通常的方法是使用exception的printStackTrace()方法:

1
2
3
4
5
6
7
8
void func() {
try {
...
} catch (RemoteException e) {
e.printStackTrace();
...
}
}

也可以只打印堆栈不退出,这样就比较方便分析代码的动态运行情况。Java代码中插入堆栈打印的方法如下

推荐

1
2
import android.util.Log;
Log.d(TAG, android.util.Log.getStackTraceString(new java.lang.Throwable()));
阅读全文 »

变量介绍

shell变量是一种很“弱”的变量,默认情况下,一个变量保存一个串,shell不关心这个串是什么含义。所以若要进行数学运算,必须使用一些命令例如let、declare、expr、双括号等。

shell变量可分为两类:局部变量和环境变量。局部变量只在创建它们的shell中可用。而环境变量则可以在创建它们的shell及其派生出来的任意子进程中使用。有些变量是用户创建的,其他的则是专用shell变量。

变量名必须以字母或下划线字符开头。其余的字符可以是字母、数字(0~9)或下划线字符。任何其他的字符都标志着变量名的终止。名字是大小写敏感的。

给变量赋值时,等号周围不能有任何空白符。为了给变量赋空值,可以在等号后跟一个换行符。

用set命令可以查看所有的变量,unset var命令可以清除变量var,var相当于没有定义过。readonly var可以把var变为只读变量,定义之后不能对var进行任何更改。

shell变量常见引用方式如下:

引用格式 含义介绍
${var} 变量值。也可以写成$var,但是不推荐。
${#var} 变量长度。例如var="HelloWorld",则${#var}返回值为10。 注意,引号””是界定符号,而不是变量中的字符。
${var:start_index} 返回从start_index开始一直到字符串结尾。
start_index为0表示从第一个字符开始,
start_index为0-x表示从倒数第x个字符开始。
例如var="0123456789"。则${var:0}返回"0123456789",${var:6}返回"6789",${var:0-3}返回”789”。
${var:start_index:length} 返回从start_index开始的length个字符,length可以为负数。var="0123456789",${var:2:5}返回"23456",${var:5:-2}返回"567"(-2表示剩余2个字符不要),${var:0-3:-1}返回"78"。
${var#string} 返回从左边删除string后的字符串,尽量短的去匹配。例如var="https://127.0.0.1/index.php", ${var#*/}返回"/127.0.0.1/index.php"
${var##string} 返回从左边删除string后的字符串,尽量长的去匹配。例如var="https://127.0.0.1/index.php",${var##*/}返回"index.php"
${var%string} 返回从右边删除string后的字符串,尽量短的去匹配。例如var="https://127.0.0.1/index.php",${var%/*}返回"https://127.0.0.1"
${var%string} 返回从右边删除string后的字符串,尽量长的去匹配。例如var="https://127.0.0.1/index.php",${var%/*}返回"https:"
${var:-newstring} 如果var为空,或者未定义,则返回newstring;否则返回原值。
${var:=newstring} 如果var为空,或者未定义,则返回newstring,并把newstring赋值给var;否则返回原值。
${var:+newstring} 如果var不为空,则返回newstring;如果var为空,则返回空值。
${var:?newstring} 如果var为空或者未定义,则将newstring写入标准错误流,本语句失败;如果var不为空,则返回原值。
${var/substring/newstring} 返回var中第一个substring被替换成newstring的字符串。例如var="2345432", ${var/3/Hello}返回"2Hello45432"
${var//substring/newstring} 返回var中所有substring被替换成newstring的字符串。例如var="2345432", ${var//3/Hello}返回"2Hello454Hello2"
$(command) 返回command命令执行后的所输出的结果。例如$(date),返回date命令执行后的输出,同date命令
$((算数表达式)) 返回双括号中算数运算的结果。例如$((20+5*6)),返回50

环境变量

环境变量的定义方法如下:

阅读全文 »
0%