脚本错误定位
脚本错误定位
常见错误
编写 Shell 脚本的时候,一定要考虑到命令失败的情况,否则很容易出错。
|
|
上面脚本中,如果目录$dir_name
不存在,cd $dir_name
命令就会执行失败。这时,就不会改变当前目录,脚本会继续执行下去,导致rm *
命令删光当前目录的文件。
如果改成下面的样子,也会有问题。
|
|
上面脚本中,只有cd $dir_name
执行成功,才会执行rm *
。但是,如果变量$dir_name
为空,cd
就会进入用户主目录,从而删光用户主目录的文件。
下面的写法才是正确的。
|
|
上面代码中,先判断目录$dir_name
是否存在,然后才执行其他操作。
如果不放心删除什么文件,可以先打印出来看一下。
|
|
上面命令中,echo rm *
不会删除文件,只会打印出来要删除的文件。
bash
的-x
参数
bash
的-x
参数可以在执行每一行命令之前,打印该命令。一旦出错,这样就比较容易追查。
下面是一个脚本script.sh
。
|
|
加上-x
参数,执行每条命令之前,都会显示该命令。
|
|
上面例子中,行首为+
的行,显示该行是所要执行的命令,下一行才是该命令的执行结果。
其实这个就是set -x
的效果,这命令我们在《set 命令和 shopt 命令》的set -x
小节学习过
环境变量
有一些环境变量常用于错位 u 定位,我们可以用这些变量来手动记录错误日志
-
LINENO:变量
LINENO
返回使用这个变量的命令在脚本里面的行号。 -
FUNCNAME:变量
FUNCNAME
返回一个数组,内容是当前的函数调用堆栈。该数组的 0 号成员是当前调用的函数,1 号成员是调用当前函数的函数,以此类推。最后一位是最开始的调用发起者,一般都是函数或者脚本名。 -
BASH_SOURCE:变量
BASH_SOURCE
返回一个数组,内容是当前的脚本调用堆栈。该数组的 0 号成员是当前执行的脚本,1 号成员是调用当前脚本的脚本,以此类推,跟变量FUNCNAME
是一一对应关系。最后一位是最开始的调用发起者,一般都是函数或者脚本名。 -
BASH_LINENO:变量
BASH_LINENO
返回一个数组,内容是每一轮调用对应的行号。${BASH_LINENO[$i]}
跟${FUNCNAME[$i]}
是一一对应关系,表示${FUNCNAME[$i]}
在调用它的脚本文件${BASH_SOURCE[$i+1]}
里面的行号。最后一个元素,即,第一个调用所在的行号,一般都是 0。
简单实践如下:
创建脚本shell2.sh
|
|
shell1.sh
|
|
main.sh
|
|
赋权后执行main.sh
|
|
直接看shell_fun2
的输出
BASH_SOURCE:main.sh
调用shell1.sh
,shell1.sh
调用shell2.sh
。
BASH_LINENO:在交互式 shell 中调用main.sh
为第 0 行(约定),main.sh
调用shell1.sh
,是在第 6 行,注释不算行,shell1.sh
调用shell2.sh
,是在第 9 行。
FUNCNAME:main 脚本调用 shell_fun1,shell_fun1 调用 shell_fun2。