文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>BASH调试器

BASH调试器

时间:2008-05-02  来源:剑心通明

感谢作者:LYOO兄[原创]
代码:
bashdb.sh负责生成debug档
#!/bin/bash
#bashdb - bash debugger
#该脚本将bashbd.pre和目标脚本处理成调试脚本

echo 'bash Debugger version 1.0'

_dbname=${0##*/}

if (( $# < 1 )); then
    echo "$_dbname: Usage: $_dbname filename" >&2
    exit 1
fi

_guineapig=$1

if [ ! -r $1 ]; then
    echo "$_dbname: Cannot read file '$_guineapig'." >&2
    exit 1
fi

shift

_tmpdir=/tmp
_libdir=.
_debugfile=$_tmpdir/bashdb.$$       #正在被调试脚本的临时文件
cat $_libdir/bashdb.pre $_guineapig > $_debugfile
exec bash $_debugfile $_guineapig $_tmpdir $_libdir "$@"

bashdb.pre负责对被调试函数进行预处理

源码:

#!/bin/bash

#bashdb预处理部分
#本文件预处理被调试的shell脚本
#参数:
#$1=初始试验脚本的名字
#$2=临时文件所保存在的目录
#$3=bashdb.pre和bashdb.fns被保存的目录

_debugfile=$0
_guineapig=$1
_tmpdir=$2
_libdir=$3

shift 3

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

            _msg "Break on condition:"
            _msg "$_brcond"
    }

    #清除单个或所有断点
    function _clearbp
    {
            local i bps

            #如果没有参数,那么删除所有断点。否则查看参数是否为正数,如果不是
            #则打印错误消息。如果是,则回应除被传递的那个之外的所有当前断点
            #并将它们赋值给局部变量。(我们需要这样做是因为将它们赋值给_linebp
            #将使数组保持在同一大小并将值向回移动一位置,导致重复值)。然后销毁旧数组
            #并将局部数组中的元素赋值,于是我们高效地重创了它,减掉了被传递的断点

            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
    }
相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载