天天看点

Bash脚本教程之脚本除错

目录

常见错误

bash的-x参数

环境变量

LINENO

FUNCNAME

BASH_SOURCE

BASH_LINENO

编写 Shell 脚本的时候,一定要考虑到命令失败的情况,否则很容易出错。

上面脚本中,如果目录<code>$dir_name</code>不存在,<code>cd $dir_name</code>命令就会执行失败。这时,就不会改变当前目录,脚本会继续执行下去,导致<code>rm *</code>命令删光当前目录的文件。

如果改成下面的样子,也会有问题。

上面脚本中,只有<code>cd $dir_name</code>执行成功,才会执行<code>rm *</code>。但是,如果变量<code>$dir_name</code>为空,<code>cd</code>就会进入用户主目录,从而删光用户主目录的文件。

下面的写法才是正确的。

上面代码中,先判断目录<code>$dir_name</code>是否存在,然后才执行其他操作。

如果不放心删除什么文件,可以先打印出来看一下。

上面命令中,<code>echo rm *</code>不会删除文件,只会打印出来要删除的文件。

<code>bash</code>的<code>-x</code>参数可以在执行每一行命令之前,打印该命令。这样就不用自己输出执行的命令,一旦出错,比较容易追查。

下面是一个脚本<code>script.sh</code>。

加上<code>-x</code>参数,执行每条命令之前,都会显示该命令。

上面例子中,行首为<code>+</code>的行,显示该行是所要执行的命令,下一行才是该命令的执行结果。

下面再看一个<code>-x</code>写在脚本内部的例子。

上面的脚本执行之后,会输出每一行命令。

输出的命令之前的<code>+</code>号,是由系统变量<code>PS4</code>决定,可以修改这个变量。

另外,<code>set</code>命令也可以设置 Shell 的行为参数,有利于脚本除错,详见《set 命令》一章。

有一些环境变量常用于除错。

变量<code>LINENO</code>返回它在脚本里面的行号。

执行上面的脚本<code>test.sh</code>,<code>$LINENO</code>会返回<code>3</code>。

变量<code>FUNCNAME</code>返回一个数组,内容是当前的函数调用堆栈。该数组的0号成员是当前调用的函数,1号成员是调用当前函数的函数,以此类推。

执行上面的脚本<code>test.sh</code>,结果如下。

上面例子中,执行<code>func1</code>时,变量<code>FUNCNAME</code>的0号成员是<code>func1</code>,1号成员是调用<code>func1</code>的主脚本<code>main</code>。执行<code>func2</code>时,变量<code>FUNCNAME</code>的0号成员是<code>func2</code>,1号成员是调用<code>func2</code>的<code>func1</code>。

变量<code>BASH_SOURCE</code>返回一个数组,内容是当前的脚本调用堆栈。该数组的0号成员是当前执行的脚本,1号成员是调用当前脚本的脚本,以此类推,跟变量<code>FUNCNAME</code>是一一对应关系。

下面有两个子脚本<code>lib1.sh</code>和<code>lib2.sh</code>。

然后,主脚本<code>main.sh</code>调用上面两个子脚本。

执行主脚本<code>main.sh</code>,会得到下面的结果。

上面例子中,执行函数<code>func1</code>时,变量<code>BASH_SOURCE</code>的0号成员是<code>func1</code>所在的脚本<code>lib1.sh</code>,1号成员是主脚本<code>main.sh</code>;执行函数<code>func2</code>时,变量<code>BASH_SOURCE</code>的0号成员是<code>func2</code>所在的脚本<code>lib2.sh</code>,1号成员是调用<code>func2</code>的脚本<code>lib1.sh</code>。

变量<code>BASH_LINENO</code>返回一个数组,内容是每一轮调用对应的行号。<code>${BASH_LINENO[$i]}</code>跟<code>${FUNCNAME[$i]}</code>是一一对应关系,表示<code>${FUNCNAME[$i]}</code>在调用它的脚本文件<code>${BASH_SOURCE[$i+1]}</code>里面的行号。

上面例子中,函数<code>func1</code>是在<code>main.sh</code>的第7行调用,函数<code>func2</code>是在<code>lib1.sh</code>的第8行调用的。

下一节Bash脚本教程之mktemp 命令,trap 命令

继续阅读