目录
常见错误
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 命令