平时在写 BASH 脚本时,总是会碰到让人抓狂的 BUG。和 C/C++ 这么丰富的调试工具相比,BASH 又有什么调试手段呢?

1 echo/print (普通技)

打印一些变量,或者提示信息。这应该是一个通用的方法了。在 BASH 里,我们可以简单的用 echo,或者 print 来输出一些 log,或者加一些 loglevel 来过滤一些 log。这里贴一下我平常用的函数:

  1. _loglevel=2
  2. DIE() {
  3. echo "Critical: $1" >&2
  4. exit 1
  5. }
  6. INFO() {
  7. [ $_loglevel -ge 2 ] && echo "INFO: $1" >&2
  8. }
  9. ERROR() {
  10. [ $_loglevel -ge 1 ] && echo "ERROR: $1" >&2
  11. }

这里的实现只是简单的加了一个 loglevel,其实可以把 log 输出到一个文件中,或者给 log 加上颜色。比如:

  1. # add color
  2. [ $_loglevel -ge 1 ] && echo -e "\033[31m ERROR:\033[0m $1" >&2
  3. # redirect to file
  4. [ $_loglevel -ge 1 ] && echo "ERROR: $1" > /var/log/xxx_log.$BASHPID

2 set -x (稀有技)

-x(xtrace) 选项会导致 BASH 在执行命令之前,先把要执行的命令打印出来。这个选项对调试一些命令错误很有帮助。

有的时候,由于传进来的参数带有一些特殊字符,导致 BASH 解析时不是按照我们预想的进行。这个时候,把 -x 打开,就能在命令执行前,把扩展后的命令打印出来。比如基于前面写的函数:

  1. set -x
  2. INFO "this is a info log"
  3. ERROR "this is a error log"
  4. set +x

然后就可以看到如下输出:

  1. + INFO 'this is a info log'
  2. + '[' 2 -ge 2 ']'
  3. + echo -e '\033[32m INFO:\033[0m this is a info log'
  4. INFO: this is a info log
  5. + ERROR 'this is a error log'
  6. + '[' 2 -ge 1 ']'
  7. + echo -e '\033[33m ERR:\033[0m this is a error log'
  8. ERR: this is a error log
  9. + set +x

如果想全程打开 xtrace,可以在执行脚本的时候加 -x 参数。

3 trap/bashdb (史诗技)

为了方便调试,BASH 也提供了陷阱机制。这跟之前介绍的两种方法高级不少。我们可以利用 trap 这个内置命令来指定各个 sigspec 应该执行的命令。trap 的具体用法如下:

  1. 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:

  1. #!/bin/bash
  2. trap "echo this is a exit echo" EXIT
  3. echo "this is a normal echo"

或者,让脚本中命令出错时,把相应的命令打印出来:

  1. #!/bin/bash
  2. trap 'echo $BASH_COMMAND return err' ERR
  3. echo this is a normal test
  4. UnknownCmd

这个脚本的输出如下:

  1. this is a normal test
  2. tt.sh: line 6: UnknownCmd: command not found
  3. UnknownCmd return err

亦或者,让脚本的命令单步执行:

  1. #!/bin/bash
  2. trap '(read -p "[$0 : $LINENO] $BASH_COMMAND ?")' DEBUG
  3. echo this is a test
  4. i=0
  5. while [ true ]
  6. do
  7. echo $i
  8. ((i++))
  9. done

其输出如下:

  1. [tt.sh : 5] echo this is a test ?
  2. this is a test
  3. [tt.sh : 7] i=0 ?
  4. [tt.sh : 8] [ true ] ?
  5. [tt.sh : 10] echo $i ?
  6. 0
  7. [tt.sh : 11] ((i++)) ?
  8. [tt.sh : 8] [ true ] ?
  9. [tt.sh : 10] echo $i ?
  10. 1
  11. [tt.sh : 11] ((i++)) ?
  12. [tt.sh : 8] [ true ] ?
  13. [tt.sh : 10] echo $i ?
  14. 2
  15. [tt.sh : 11] ((i++)) ?

是不是有点意思了?其实有一个 bashdb 的开源项目,也是利用 trap 机制,模拟 gdb 做了一个 bash 脚本的调试器。它本身也是一个 bash 脚本。在加载要调试的脚本后,可以用和 gdb 类似的命令,甚至缩写也是一样的,大家可以尝试一下:)

(上个月沉迷于 Diablo3,最后发现自己脸不行,悴!还是回来写点东西吧!)

BASH 的调试技巧的更多相关文章

  1. 《Debug Hacks》和调试技巧【转】

    转自:https://blog.csdn.net/sdulibh/article/details/46462529 Debug Hacks 作者为吉冈弘隆.大和一洋.大岩尚宏.安部东洋.吉田俊辅,有中 ...

  2. Java项目调试技巧及版本控制

    开发项目中,调试是必不可少的. 本篇博客从以下4个方面介绍项目调试技巧: 响应状态码的含义 服务端断点调试技巧 客户端断点调试技巧 设置日志级别,并将日志输出到不同的终端 以及,最后简单的介绍了一下g ...

  3. 【工具】VS2010常用调试技巧(1)

    调试是一个程序员最基本的技能,其重要性不言自明.不会调试的程序员就意味着他即使会一门语言,却不能编制出好的软件.本文就本人在开发过程中常用的调试技巧作下简单呢介绍,希望对大家有所帮助,能力超群者请绕道 ...

  4. Visual Studio高级调试技巧

    1. 设置软件断点,运行到目标位置启动调试器 方法①:使用汇编指令(注:x64 c++不支持嵌入汇编) _asm 方法②:编译器提供的方法 __debugbreak(); 方法③:使用windows ...

  5. 【转】你所不知道的Android Studio调试技巧

    这篇写Android studio debug技巧个人觉得写得不错,转自:http://www.jianshu.com/p/011eb88f4e0d# Android Studio目前已经成为开发An ...

  6. VS调试技巧,提高调试效率(转):

    如果你还没有使用过这些技巧,希望这篇博文能帮你发现它们. 它们学起来很容易,能帮你节省很多时间. 运行到光标(Ctrl+ F10) 我经常看见人们是这样来调试应用程序的: 他们在应用程序需要调试的代码 ...

  7. iOS各种调试技巧豪华套餐

    转载自http://www.cnblogs.com/daiweilai/p/4421340.html 目录 前言 逼优鸡 知己知彼 百战不殆 抽刀断Bug 普通操作 全局断点(Global Break ...

  8. xcode调试技巧

    xode报错有时挺无厘头,完全不知道哪里出的问题,最后还得用排除法,记录一些工作中认为有用的调试技巧 1.左侧视图点断点视图,左下角点加号,选择exception breakpoint,类型选c++, ...

  9. 你所不知道的Android Studio调试技巧

    转载:http://www.jianshu.com/p/011eb88f4e0d Android Studio目前已经成为开发Android的主要工具,用熟了可谓相当顺手.作为开发者,调试并发现bug ...

随机推荐

  1. struts标签错误:Can not find the tag library descriptor for "http://java.sun.com/jsp/jstl/core"

    今天使用eclipse开发ssh,出现Can not find the tag library descriptor for "http://java.sun.com/jsp/jstl/co ...

  2. VS Code 配置删除左边单词快捷键(同Sublime 和 Atom)

    VS Code 中删除一行的快捷键默认是 cmd + shift + k,或者使用简介 cmd + x,对于一个长期使用 Sublime 和 Atom 的程序猿来说,在VS Code 上删除行,特别是 ...

  3. cmd下常用命令汇总

    1.获得文件夹内所有文件的文件名列表 dir *.png /b>list.txt 其中: (1)*.png表示筛选后缀为.png的文件 (2)/b为输出的模式.如下: 引用 /b 只有文件名  ...

  4. 说说asp.net中的异常处理和日志追踪

    关于异常的处理想必大家都了解try{}catch(){}finally{},这里就不再讲了.通过在VS里的"调试"-"异常",在弹出的异常对话框里的Common ...

  5. placeholder样式设置

    在input框中有时想将输入的字和placeholder设为不同的颜色或其它效果,这时就可以用以下代码来对placeholder进行样式设置了. ::-webkit-input-placeholder ...

  6. php审计学习:xdcms2.0.8注入

    注入点Fields: 注册页面会引用如下方法: $fields 变量是从 $fields=$_POST['fields']; 这里获取, 在代码里没有过滤. 打印 fields 数据查看: 从代码上看 ...

  7. js日期工具

    /** * 日期工具类 */ define(function(require, exports, module) { var constants = require("constants&q ...

  8. YAML中使用Jinja模板以{{ foo }}开头需要整行加双引号

    YAML陷阱 YAML语法要求如果值以{{ foo }}开头的话我们需要将整行用双引号包起来.这是为了确认你不是想声明一个YAML字典.该知识点在 YAML 语法 页面有所讲述. 这样是不行的: - ...

  9. HDU 2859 Phalanx(二维DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2859 题目大意:对称矩阵是这样的矩阵,它由“左下到右”线对称. 相应位置的元素应该相同. 例如,这里是 ...

  10. spring源码分析---事务篇

    上一篇我介绍了spring事务的传播特性和隔离级别,以及事务定义的先关接口和类的关系.我们知晓了用TransactionTemplate(或者直接用底层P的latformTransactionMana ...