source $_libdir/bashdb.fns declare -a _linebp let _trace=0 let _i=1
while read; do _lines[$_i]=$REPLY let _i=$_i+1 done < $_guineapig
trap _cleanup EXIT let _steps=1 LINENO=-2 trap '_steptrap $LINENO' DEBUG
bashdb.fns包含了DEBUG调用的调试函数
源码:
#!/bin/bash
#测试脚本的每行被执行之后,shell进入本函数
function _steptrap { _curline=$1 #当前运行行的行号 (( $_trace )) && _msg "$PS4 line $_curline: ${_lines[$_curline]}"
if (( $_steps >= 0 )); then let _steps=$_steps-1 fi
#首先查看是否达到行编号断点 #如果达到,则进入调试器 if _at_linenumbp then _msg "Reached breakpoint at line $_curline" _cmdloop
#如果没有达到,则检查是否有中断条件存在且为真 #如果是,则进入调试器 elif [ -n "$_brcond" ] && eval $_brcond; then _msg "Bread condition $_brcond true at line $_curline" _cmdloop
#如果不是,则检查是否在采用步进方式,步数是否达到。如果是,则进入调试器 elif (( $_steps == 0 )); then _msg "Stopped at line $_curline" _cmdloop fi }
#调试器命令循环
function _cmdloop { local cmd args
while read -e -p "bashdb> " cmd args; do case $cmd in h ) _menu ; #打印命令菜单 bc) _setbc $args ; #设置中断条件 bp) _setbp $args ; #设置断点在给定行 cb) _clearbp $args ; #清除一个或所有断点 ds) _displayscript ; #列出脚本并显示断点 g ) return ; #开始/再继续执行脚本 q ) exit ; #退出 s ) let _steps=${args:-1} #单步执行N次(默认为1) return ; x ) _xtrace ; #切换执行追踪 !*) eval ${cmd#!} $args ; #传递给shell * ) _msg "Invalid command: '$cmd'" ; esac done }
#查看这个行编号是否有一个断点 function _at_linenumbp { local i=0
#循环遍历断点数组并查看它们是否与当前行编号匹配。如果匹配就返回真(0), #否则就返回假
if [ "$_linebp" ]; then while (( $i < ${#_linebp[@]} )); do if (( ${_linebp[$i]} == $_curline )); then return 0 fi let i=$i+1 done fi return 1 }
#设置断点在给定的行编号或列出断点 function _setbp { local i #如果无参数,调用断点列表函数。否则查看参数是否为正数 #如果不是,则打印错误消息。如果是,则查看行编号是否包含文本 #如果不是则打印错误信息。如果是,则回应当前断点和新的附加。并将它们 #输送到"排序",并将结果赋值给断点列表。这将导致断点按数字顺序排列
#注意,使用-u选项可以删除重复的断点
if [ -z "$1" ]; then _listbp elif [ $(echo $1 | grep '^[0-9]*') ]; then if [ -n "${_lines[$1]}" ]; then _linebp=($(echo $( (for i in "${_linebp[*]} $1"; do echo $i; done) | sort -n) )) _msg "Breakpoint set at line $1" else _msg "Breakpoints can only be set on non-blank lines" fi else _msg "Please specify a numeric line number" fi }
#列出断点及中断条件 function _listbp { if [ -n "$_linebp" ]; then _msg "Breakpoints at lines: ${_linebp[*]}" else _msg "No breakpoints have been set" fi
if [ -z "$1" ]; then unset _linebp[*] _msg "All breakpoints have been cleared" elif [ $(echo $1 | grep '^[0-9]*') ]; then bps=($(echo $(for i in ${_linebp[*]}; do if (( $1 != $i )); then echo $i; fi; done) )) unset _linebp[*] _linebp=(${bps[*]}) _msg "Breakpoint cleared at line $1" else _msg "Please specify a numeric line number" fi }
#设置或清除中断条件 function _setbc { if [ -n "$*" ]; then _brcond=$args _msg "Break when true: $_brcond" else _brcond= _msg "Break condition cleared" fi }
#打印出shell脚本并标出断点的位置以及当前行 function _displayscript { local i=1 j=0 bp cl ( while (( $i <= ${#_lines[@]} )); do if [ ${_linebp[$j]} ] && (( ${_linebp[$j]} == $i )); then bp='*' let j=$j+1 else bp='' fi if (( $_curline == $i )); then cl=">" else cl="" fi echo "$i:$bp $cl ${_lines[$i]}" let i=$i+1 done ) | more }
#切换执行追踪on/off function _xtrace { let _trace="! $_trace" _msg "Execution trace " if (( $_trace )); then _msg "on" else _msg "off" fi }
#打印传进来的参数到标准错误 function _msg { echo -e "$@" >&2 }
#打印命令菜单 function _menu { _msg 'bashdb commands: bp N set breakpoint at line N bp list breakpoints and break condition bc string set break condition to string bc clear break condition cb N clear breakpoint at line N cb clear all breakpoints ds displays the test script and breakpoints g start/resume execution s [N] execute N statements (default 1) x toggle execution trace on/off h,? print this menu ! string passes string to a shell q quit' }
#退出之前删除临时文件 function _cleanup { rm $_debugfile 2>/dev/null }