BASH 的调试技巧
平时在写 BASH 脚本时,总是会碰到让人抓狂的 BUG。和 C/C++ 这么丰富的调试工具相比,BASH 又有什么调试手段呢?
1 echo/print (普通技)
打印一些变量,或者提示信息。这应该是一个通用的方法了。在 BASH 里,我们可以简单的用 echo,或者 print 来输出一些 log,或者加一些 loglevel 来过滤一些 log。这里贴一下我平常用的函数:
- _loglevel=2
- DIE() {
- echo "Critical: $1" >&2
- exit 1
- }
- INFO() {
- [ $_loglevel -ge 2 ] && echo "INFO: $1" >&2
- }
- ERROR() {
- [ $_loglevel -ge 1 ] && echo "ERROR: $1" >&2
- }
这里的实现只是简单的加了一个 loglevel,其实可以把 log 输出到一个文件中,或者给 log 加上颜色。比如:
- # add color
- [ $_loglevel -ge 1 ] && echo -e "\033[31m ERROR:\033[0m $1" >&2
- # redirect to file
- [ $_loglevel -ge 1 ] && echo "ERROR: $1" > /var/log/xxx_log.$BASHPID
2 set -x (稀有技)
-x(xtrace) 选项会导致 BASH 在执行命令之前,先把要执行的命令打印出来。这个选项对调试一些命令错误很有帮助。
有的时候,由于传进来的参数带有一些特殊字符,导致 BASH 解析时不是按照我们预想的进行。这个时候,把 -x 打开,就能在命令执行前,把扩展后的命令打印出来。比如基于前面写的函数:
- set -x
- INFO "this is a info log"
- ERROR "this is a error log"
- set +x
然后就可以看到如下输出:
- + INFO 'this is a info log'
- + '[' 2 -ge 2 ']'
- + echo -e '\033[32m INFO:\033[0m this is a info log'
- INFO: this is a info log
- + ERROR 'this is a error log'
- + '[' 2 -ge 1 ']'
- + echo -e '\033[33m ERR:\033[0m this is a error log'
- ERR: this is a error log
- + set +x
如果想全程打开 xtrace,可以在执行脚本的时候加 -x
参数。
3 trap/bashdb (史诗技)
为了方便调试,BASH 也提供了陷阱机制。这跟之前介绍的两种方法高级不少。我们可以利用 trap 这个内置命令来指定各个 sigspec 应该执行的命令。trap 的具体用法如下:
- trap [-lp] [[arg] sigspec ...]
sigspec 包括 <signal.h>
中定义的各个 signal, EXIT,ERR,RETURN 和 DEBUG。
各个 signal 这里就不介绍了。EXIT 会在 shell 退出时执行指定的命令。若当前 shell 中有命令执行返回非零值,则会执行与 ERR 相关联的命令。而 RETURN 是针对 source
和 .
,每次执行都会触发 RETURN 陷阱。若绑定一个命令到 DEBUG,则会在每一个命令执行之前,都会先执行 DEBUG 这个 trap。这里要注意的是,ERR 和 DEBUG 只在当前 shell 有效。若想函数和子 shell 自动继承这些 trap,则可以设置 -T(DEBUG/RETURN) 和 -E(ERR)。
比如,下面的脚本会在退出时,执行echo:
- #!/bin/bash
- trap "echo this is a exit echo" EXIT
- echo "this is a normal echo"
或者,让脚本中命令出错时,把相应的命令打印出来:
- #!/bin/bash
- trap 'echo $BASH_COMMAND return err' ERR
- echo this is a normal test
- UnknownCmd
这个脚本的输出如下:
- this is a normal test
- tt.sh: line 6: UnknownCmd: command not found
- UnknownCmd return err
亦或者,让脚本的命令单步执行:
- #!/bin/bash
- trap '(read -p "[$0 : $LINENO] $BASH_COMMAND ?")' DEBUG
- echo this is a test
- i=0
- while [ true ]
- do
- echo $i
- ((i++))
- done
其输出如下:
- [tt.sh : 5] echo this is a test ?
- this is a test
- [tt.sh : 7] i=0 ?
- [tt.sh : 8] [ true ] ?
- [tt.sh : 10] echo $i ?
- 0
- [tt.sh : 11] ((i++)) ?
- [tt.sh : 8] [ true ] ?
- [tt.sh : 10] echo $i ?
- 1
- [tt.sh : 11] ((i++)) ?
- [tt.sh : 8] [ true ] ?
- [tt.sh : 10] echo $i ?
- 2
- [tt.sh : 11] ((i++)) ?
是不是有点意思了?其实有一个 bashdb 的开源项目,也是利用 trap 机制,模拟 gdb 做了一个 bash 脚本的调试器。它本身也是一个 bash 脚本。在加载要调试的脚本后,可以用和 gdb 类似的命令,甚至缩写也是一样的,大家可以尝试一下:)
(上个月沉迷于 Diablo3,最后发现自己脸不行,悴!还是回来写点东西吧!)
BASH 的调试技巧的更多相关文章
- 《Debug Hacks》和调试技巧【转】
转自:https://blog.csdn.net/sdulibh/article/details/46462529 Debug Hacks 作者为吉冈弘隆.大和一洋.大岩尚宏.安部东洋.吉田俊辅,有中 ...
- Java项目调试技巧及版本控制
开发项目中,调试是必不可少的. 本篇博客从以下4个方面介绍项目调试技巧: 响应状态码的含义 服务端断点调试技巧 客户端断点调试技巧 设置日志级别,并将日志输出到不同的终端 以及,最后简单的介绍了一下g ...
- 【工具】VS2010常用调试技巧(1)
调试是一个程序员最基本的技能,其重要性不言自明.不会调试的程序员就意味着他即使会一门语言,却不能编制出好的软件.本文就本人在开发过程中常用的调试技巧作下简单呢介绍,希望对大家有所帮助,能力超群者请绕道 ...
- Visual Studio高级调试技巧
1. 设置软件断点,运行到目标位置启动调试器 方法①:使用汇编指令(注:x64 c++不支持嵌入汇编) _asm 方法②:编译器提供的方法 __debugbreak(); 方法③:使用windows ...
- 【转】你所不知道的Android Studio调试技巧
这篇写Android studio debug技巧个人觉得写得不错,转自:http://www.jianshu.com/p/011eb88f4e0d# Android Studio目前已经成为开发An ...
- VS调试技巧,提高调试效率(转):
如果你还没有使用过这些技巧,希望这篇博文能帮你发现它们. 它们学起来很容易,能帮你节省很多时间. 运行到光标(Ctrl+ F10) 我经常看见人们是这样来调试应用程序的: 他们在应用程序需要调试的代码 ...
- iOS各种调试技巧豪华套餐
转载自http://www.cnblogs.com/daiweilai/p/4421340.html 目录 前言 逼优鸡 知己知彼 百战不殆 抽刀断Bug 普通操作 全局断点(Global Break ...
- xcode调试技巧
xode报错有时挺无厘头,完全不知道哪里出的问题,最后还得用排除法,记录一些工作中认为有用的调试技巧 1.左侧视图点断点视图,左下角点加号,选择exception breakpoint,类型选c++, ...
- 你所不知道的Android Studio调试技巧
转载:http://www.jianshu.com/p/011eb88f4e0d Android Studio目前已经成为开发Android的主要工具,用熟了可谓相当顺手.作为开发者,调试并发现bug ...
随机推荐
- == 和 equals,equals 与 hashcode,HashSet 和 HashMap,HashMap 和 Hashtable
一:== 和 equals == 比较引用的地址equals 比较引用的内容 (Object 类本身除外) String obj1 = new String("xyz"); Str ...
- 最短路+找规律 Samara University ACM ICPC 2016-2017 Quarterfinal Qualification Contest L. Right Build
题目链接:http://codeforces.com/gym/101149/problem/L 题目大意:有n个点(其实是n+1个点,因为编号是0~n),m条有向边.起点是0,到a和b两个节点,所经过 ...
- MYSQL5.6学习——mysqldump备份与恢复
MYSQL备份 冷备份:停止服务进行备份,即停止数据库的写入 热备份:不停止服务进行备份(在线) l mysql的MyIsam引擎只支持冷备份,InnoDB支持热备份,原因: InnoDB引擎是事务 ...
- Jdbc练习
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import ...
- Razor使用Parse()时最好指定“缓存名”
为什么? 本文的标题,明显有一种提醒的口吻. 从18年的生活经验看,如果想提醒人要怎么办,不要怎么办. 最好说明原因.那么小编开始说明原因喽. 哦对,说原因之前,先说交代一下背景,一句话 在非mvc下 ...
- Name That Number 命名那个数字
1.2.3 Name That Number 命名那个数字 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 183 Solved: 33[Submit][ ...
- 2016CCPC东北地区大学生程序设计竞赛 (2018年8月22日组队训练赛)
题目链接:http://acm.hdu.edu.cn/search.php?field=problem&key=2016CCPC%B6%AB%B1%B1%B5%D8%C7%F8%B4%F3%D ...
- tar解压与压缩
1.解压 tar -zxvf 压缩文件名 -C 指定的目录 (制定的目录必须存在) 2.压缩 tar -czvf 压缩后的文件名 要压缩的文件夹
- 47、求1+2+3+...+n
一.题目 求1+2+3+...+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C). 二.解法 public class Solut ...
- http 之cookie和session
cookie和session 关于http: 1.http是:无状态.短连接 2.http的请求生命周期:给服务端发送一个请起头,通过域名提取url,通过路由关系匹配,再通过函数+html进行模板加 ...