Debug your shell scripts with bashdb
来源:互联网 发布:基金 模拟投资 软件 编辑:程序博客网 时间:2024/05/09 05:53
The Bash Debugger Project (bashdb) lets you set breakpoints, inspect variables, perform a backtrace, and step through a bash script line by line. In other words, it provides the features you expect in a C/C++ debugger to anyone programming a bash script.
To see if your standard bash executable has bashdb support, execute the command shown below; if you are not taken to a bashdb prompt then you'll have to install bashdb yourself.
$ bash --debugger -c "set|grep -i dbg"...bashdb<0>
The Ubuntu Intrepid repository contains a package for bashdb, but there is no special bashdb package in the openSUSE 11 or Fedora 9 repositories. I built from source using version 4.0-0.1 of bashdb on a 64-bit Fedora 9 machine, using the normal./configure; make; sudo make install
commands.
You can start the Bash Debugger using the bash --debugger foo.sh
syntax or thebashdb foo.sh
command. The former method isrecommended except in cases where I/O redirection might cause issues, and it's what I used. You can also use bashdb throughddd or from anEmacs buffer.
The syntax for many of the commands in bashdb mimics that of gdb, the GNU debugger. You canstep
into functions, usenext
to execute the next line without stepping into any functions, generate a backtrace withbt
, exit bashdb withquit
or Ctrl-D, and examine a variable withprint $foo
. Aside from the prefixing of the variable with$
at the end of the last sentence, there are some other minor differences that you'll notice. For instance, pressing Enter on a blank line in bashdb executes the previous step or next command instead of whatever the previous command was.
The print command forces you to prefix shell variables with the dollar sign ($foo
). A slightly shorter way of inspecting variables and functions is to use thex foo
command, which usesdeclare
to print variables and functions.
Both bashdb and your script run inside the same bash shell. Because bash lacks some namespace properties, bashdb will include some functions and symbols into the global namespace which your script can get at. bashdb prefixes its symbols with_Dbg_
, so you should avoid that prefix in your scripts to avoid potential clashes. bashdb also uses some environment variables; it uses theDBG_
prefix for its own, and relies on some standard bash ones that begin withBASH_
.
To illustrate the use of bashdb, I'll work on the small bash script below, which expects a numeric argumentn
and calculates the nthFibonacci number.
#!/bin/bashversion="0.01";fibonacci() { n=${1:?If you want the nth fibonacci number, you must supply n as the first parameter.} if [ $n -le 1 ]; then echo $n elsel=`fibonacci $((n-1))`r=`fibonacci $((n-2))`echo $((l + r)) fi}for i in `seq 1 10`do result=$(fibonacci $i) echo "i=$i result=$result"done
The below session shows bashdb in action, stepping over and then into the fibonacci function and inspecting variables. I've made my input text bold for ease of reading. An initial backtrace (bt
) shows that the script begins at line 3, which is where the version variable is written. The next
and list
commands then progress to the next line of the script a few times and show the context of the current execution line. After one of thenext
commands I press Enter to execute next
again. I invoke theexamine
command through the single letter shortcutx
. Notice that the variables are printed out usingdeclare
as opposed to their display on the next line usingprint
. Finally I set a breakpoint at the start of thefibonacci
function andcontinue
the execution of the shell script. Thefibonacci
function is called and I move to thenext
line a few times and inspect a variable.
$ bash --debugger ./fibonacci.sh ... (/home/ben/testing/bashdb/fibonacci.sh:3): 3: version="0.01"; bashdb<0> bt ->0 in file `./fibonacci.sh' at line 3 ##1 main() called from file `./fibonacci.sh' at line 0 bashdb<1> next (/home/ben/testing/bashdb/fibonacci.sh:16): 16: for i in `seq 1 10` bashdb<2> list 16:==>for i in `seq 1 10` 17: do 18: result=$(fibonacci $i) 19: echo "i=$i result=$result" 20: done bashdb<3> next (/home/ben/testing/bashdb/fibonacci.sh:18): 18: result=$(fibonacci $i) bashdb<4> (/home/ben/testing/bashdb/fibonacci.sh:19): 19: echo "i=$i result=$result" bashdb<5> x i result declare -- i="1" declare -- result="" bashdb<7> print $i $result 1 bashdb<10> break fibonacci Breakpoint 1 set in file /home/ben/testing/bashdb/fibonacci.sh, line 5. bashdb<11> continue Breakpoint 1 hit (1 times). (/home/ben/testing/bashdb/fibonacci.sh:5): 5: fibonacci() { bashdb<(12)> next (/home/ben/testing/bashdb/fibonacci.sh:6): 6: n=${1:?If you want the nth fibonacci number, you must supply n as the first parameter.} bashdb<(13)> next (/home/ben/testing/bashdb/fibonacci.sh:7): 7: if [ $n -le 1 ]; then bashdb<(14)> x n declare -- n="2" bashdb<(15)> quit
Notice that the number in the bashdb prompt toward the end of the above example is enclosed in parentheses. Each set of parentheses indicates that you have entered a subshell. In this example this is due to being inside a shell function.
In the below example I use a watchpoint to see if and where the result
variable changes. Notice the initialnext
command. I found that if I didn't issue that next then my watch would fail to work. As you can see, after I issuec
to continue execution, execution is stopped whenever the result variable is about to change, and the new and old value are displayed.
(/home/ben/testing/bashdb/fibonacci.sh:3): 3: version="0.01"; bashdb<0> next (/home/ben/testing/bashdb/fibonacci.sh:16): 16: for i in `seq 1 10` bashdb<1> watch result 0: ($result)==0 arith: 0 bashdb<2> c Watchpoint 0: $result changed: old value: '' new value: '1' (/home/ben/testing/bashdb/fibonacci.sh:19): 19: echo "i=$i result=$result" bashdb<3> c i=1 result=1 i=2 result=1 Watchpoint 0: $result changed: old value: '1' new value: '2' (/home/ben/testing/bashdb/fibonacci.sh:19): 19: echo "i=$i result=$result"
To get around the strange initial next
requirement I used the watche
command in the below session, which lets you stop whenever an expression becomes true. In this case I'm not overly interested in the first few Fibonacci numbers so I set a watch to have execution stop when the result is greater than 4. You can also use a watche
command without a condition; for example, watche result
would stop execution whenever the result variable changed.
$ bash --debugger ./fibonacci.sh (/home/ben/testing/bashdb/fibonacci.sh:3): 3: version="0.01"; bashdb<0> watche result > 4 0: (result > 4)==0 arith: 1 bashdb<1> continue i=1 result=1 i=2 result=1 i=3 result=2 i=4 result=3 Watchpoint 0: result > 4 changed: old value: '0' new value: '1' (/home/ben/testing/bashdb/fibonacci.sh:19): 19: echo "i=$i result=$result"
When a shell script goes wrong, many folks use the time-tested method of incrementally adding inecho
orprintf
statements to look for invalid values or code paths that are never reached. With bashdb, you can save yourself time by just adding a few watches on variables or setting a few breakpoints.
Ben Martin has been working on filesystems for more than 10 years. He completed his Ph.D. and now offers consulting services focused on libferris, filesystems, and search solutions.
- Debug your shell scripts with bashdb
- shell bashdb debug
- Control your scripts with command-line PHP
- bashdb调试shell脚本
- HOW-TO:Debug Python Scripts with Eclipse
- HOW-TO:Debug Python Scripts with Eclipse
- How do I debug UiAutomator scripts with Eclipse
- How do I debug UIAutomator scripts with Eclipse
- shell scripts
- shell scripts
- Shell Scripts
- shell scripts
- Bash Special Parameters Explained with 4 Example Shell Scripts
- Scripts control your webpages
- Debug your Java code with ease using JPDA
- Debug your PHP in Docker with Intellij/PHPStorm and Xdebug
- yesterday shell scripts
- linux shell scripts
- Android 模拟键盘鼠标事件
- 论缓存之第二<近与快>
- 一个MYSQL多值查询的存储过程
- paxos问题与相关的资料记下,回头再好好整理
- C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast和const_cast
- Debug your shell scripts with bashdb
- spring2.0-2.5-3.0变化[转]
- CentOS装LAMP服务器(Apache2+PHP5+MySQL)
- 用echo命令修改用户密码
- J2SE代码例子收集(IO)
- sql plus中帮定变量的使用
- vs 快捷键
- 制作zip压缩包
- 开源框架spring详解-----AOP的深刻理解