Shell脚本的简单排错法及调试程序bashdb

Jboss 的研究稍有卡壳,那就来点基础教程好了。

与众多脚本语言一样,Shell 脚本在执行时出错是很常见的,最简单的原因无外乎脚本在编写的过程中出现了语法错误或者不小心输错了命令等。找出脚本中的错误是很重要的能力。比如,我经常不小心会把 echo 命令写成了 ehco,那么执行就会出现下面这种情况:

[root@localhost ~]# sh test
test: line 2: ehco: command not found

从报错信息很容易判断出错的原因是“命令不存在”。重新编辑这个文件修改成 echo 就可以解决。如果只是语法或命令上的错误还是比较容易辨别的,但往往一些逻辑或算法错误就不容易发现,因为语法正确且本身不会造成程序运行错误。比如说下面的脚本,本来想连续 10 次做某些操作的,结果却迟迟没输出。仔细观察一下就知道是陷入了死循环。

[root@localhost ~]# cat test
#!/bin/bash
for ((i=10;i>0;i=i+1))
    do
         #run command there
    done

如果在上面的循环中加入 echo 语句,就容易发现问题了。而如果是单次循环过快,根本来不及看就进入了下一次循环,那这时就可以加入 sleep 命令降低单次循环的速度,比如使用 sleep 2,单次循环就将延时 2s,给我们带来足够的观察时间:

[root@localhost ~]# cat test
#!/bin/bash
for ((i=10;i>0;i=i+1))
    do
         #run command there
         echo "i=$i";
    done

为了更清晰的看到脚本运行的过程,我们还可以借助-x 参数来观察脚本的运行情况。比如上面的脚本,我们使用-x 参数执行就可以发现,变量 i 的值一直在增加,且一直满足 x>0 的条件,所以这是一个死循环。所以,我们只要将 i=i+1 修改成 i=i-1 即可。

[root@localhost ~]# sh -x test
+ (( i=10 ))
+ (( i>0 ))
+ echo i=10
i=10
+ sleep 2
+ (( i=i+1 ))
+ (( i>0 ))
+ echo i=11
i=11
+ sleep 2
+ (( i=i+1 ))
+ (( i>0 ))
+ echo i=12
i=12
+ sleep 2
[Ctrl +c]终止脚本

Shell 本身并没有提供更好的排错工具,为了更加精细地调试 Shell 脚本,我们可以借助第三方工具 bashdb。这是一个类似于 GDB 的脚本调试软件,小巧而强大,具有这只断点、单步执行、观察变量等功能。下载时请根据所使用的 bash 版本选择相应的 bashdb,否则会提示因为版本不符合而无法安装。

如下查看 bash 版本:

[root@localhost ~]# bash --version
GNU bash, version 3.1.25(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.

下载地址

如下安装:

#第一步:在终端使用wget下载3.1版本
wget  http://ftp.jaist.ac.jp/pub/sourceforge/b/ba/bashdb/bashdb/3.1-0.09/bashdb-3.1-0.09.tar.gz
#第二步:解压并进入目录
tar -zxvf  bashdb-3.1-0.09.tar.gz
cd  bashdb-3.1-0.09
#第三步:配置及编译安装
./configure
make && make install

安装完成后,我们便可以在终端使用 bashdb 命令了,改命令典型用法如下:

[root@localhost ~]# bashdb --debug 脚本名

常用参数:

一、列出代码和查询代码类:
l  列出当前行以下的10行
-  列出正在执行的代码行的前面10行
.  回到正在执行的代码行
w  列出正在执行的代码行前后的代码
/pat/ 向后搜索pat
?pat?向前搜索pat
二、Debug控制类:
h     帮助
help  命令 得到命令的具体信息
q     退出bashdb
x     算数表达式 计算算数表达式的值,并显示出来
!!    空格Shell命令 参数 执行shell命令
使用bashdb进行debug的常用命令(cont.)
三、控制脚本执行类:
n   执行下一条语句,遇到函数,不进入函数里面执行,将函数当作黑盒
s n 单步执行n次,遇到函数进入函数里面
b   行号n 在行号n处设置断点
del 行号n 撤销行号n处的断点
c   行号n 一直执行到行号n处
R   重新启动当前调试脚本
Finish 执行到程序最后
cond n expr 条件断点

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

终于遇到goroutine死锁的BUG了

今天测试用Go语言写的角色服务器,发现在模拟大量客户端获取角色列表的时候会卡住,但是服务器程序的CPU占用率为零。分析并经过代码检查确认是goroutine死锁...

478150
来自专栏Golang语言社区

GDB使用详解

一、打开GDB 1、gdb filename 加载该文件到gdb 2、gdb file filename 如果gdb filename失败,可以在打开gd...

378100
来自专栏Coding迪斯尼

java开发系统内核:创建文件操作API

16130
来自专栏惨绿少年

shell编程下 特殊变量、test / [ ]判断、循环、脚本排错

第1章 shell中的特殊变量 1.1 $# $# 表示参数的个数 1.1.1 【示例】脚本内容 [root@znix ~]# cat /server/scri...

24400
来自专栏Python

linux每日命令(23):find命令之xargs

在使用 find命令的-exec选项处理匹配到的文件时, find命令将所有匹配到的文件一起传递给exec执行。但有些系统对能够传递给exec的命令长度有限制,...

10820
来自专栏北京马哥教育

Python爬虫基础知识:urllib2的使用技巧

糖豆贴心提醒,本文阅读时间6分钟 前面说到了urllib2的简单入门,下面整理了一部分urllib2的使用细节。 1.Proxy 的设置 urllib2 默认...

31650
来自专栏架构之路

Linux下的make命令用法

Linux 下 make 命令是系统管理员和程序员用的最频繁的命令之一。管理员用它通过命令行来编译和安装很多开源的工具,程序员用它来管理他们大型复杂的项目编译问...

54740
来自专栏程序员阿凯

一条大河波浪宽 -- 数据库连接池实现

12440
来自专栏java一日一条

Java EE7和Maven工程入门(4)

1.一个web maven模块(war) 2.一个支持无状态会话beans的ejb模块(EJB3.1) 3.支持实体beans的ejb模块(JPA2)

8010
来自专栏Jed的技术阶梯

Kafka 新版消费者 API(一):订阅主题

说明:这两个参数分别指定了 TCP socket 接收和发送数据包的缓冲区大小。如果它们被设为 -1,就使用操作系统的默认值。如果生产者或消费者与 broker...

96320

扫码关注云+社区

领取腾讯云代金券