Shell脚本调试技术

本文最后更新于2015年12月12日,已超过 1 年没有更新,如果文章内容失效,还请反馈给我,谢谢!

=Start=

前段时间写Shell脚本比较多,对shell脚本的调试技术/技巧有一定需求。然后通过一些总结和针对性的搜索,就有了这篇文章。

内容

对”-x”选项的增强

“-x”执行选项是目前最常用的跟踪和调试shell脚本的手段,但其输出的调试信息仅限于进行变量替换之后的每一条实际执行的命令以及行首的一个”+”号提示符,居然连行号这样的重要信息都没有,对于复杂的shell脚本的调试来说,还是非常的不方便。幸运的是,我们可以巧妙地利用shell内置的一些环境变量来增强”-x”选项的输出信息,下面先介绍几个shell内置的环境变量:

$LINENO

代表shell脚本的当前行号,类似于C语言中的内置宏__LINE__

$FUNCNAME

函数的名字,类似于C语言中的内置宏__func__,但宏__func__只能代表当前所在的函数名,而$FUNCNAME的功能更强大,它是一个数组变量,其中包含了整个调用链上所有的函数的名字,故变量${FUNCNAME[0]}代表shell脚本当前正在执行的函数的名字,而变量${FUNCNAME[1]}则代表调用函数${FUNCNAME[0]}的函数的名字,余者可以依此类推。

$PS4

主提示符变量$PS1和第二级提示符变量$PS2比较常见,但很少有人注意到第四级提示符变量$PS4的作用。我们知道使用“-x”执行选项将会显示shell脚本中每一条实际执行过的命令,而$PS4的值将被显示在“-x”选项输出的每一条命令的前面。在Bash Shell中,缺省的$PS4的值是”+”号。(现在知道为什么使用”-x”选项时,输出的命令前面有一个”+”号了吧?)。

利用$PS4这一特性,通过使用一些内置变量来重定义$PS4的值,我们就可以增强”-x”选项的输出信息。例如先执行export PS4=’+{$LINENO:${FUNCNAME[0]}} ‘, 然后再使用“-x”选项来执行脚本,就能在每一条实际执行的命令前面显示其行号以及所属的函数名。

set -x
export PS4='+{${FUNCNAME[0]}@$LINENO}'
export PS4='+${BASH_SOURCE}:${LINENO}:${FUNCNAME[0]}: '

$ man bash
PS1    The value of this parameter is expanded (see PROMPTING below) and used as the primary prompt string.  The default value is ``\s-\v\$ ''.
PS2    The value of this parameter is expanded as with PS1 and used as the secondary prompt string.  The default is ``> ''.
PS3    The value of this parameter is used as the prompt for the select command (see SHELL GRAMMAR above).
PS4    The value of this parameter is expanded as with PS1 and the value is printed before each command bash displays during an execution trace. The first character of PS4 is replicated multiple times, as necessary, to indicate multiple levels of indirection. The default is ``+ ''.
参考链接

=EOF=

声明: 除非注明,ixyzero.com文章均为原创,转载请以链接形式标明本文地址,谢谢!
https://ixyzero.com/blog/archives/2562.html

7 thoughts on “Shell脚本调试技术”

  1. Bash的提示符

    PS1:用户bash的交互提示符,主提示符。

    PS2:第二提示符,主要用在一些除了PS1之外常见的提示符场景,比如输入了`’`之后回车,就能看到这个提示符。

    PS3:用于select语句的交互提示符。

    PS4:用于跟踪执行过程时的提示符,一般显示为`+`。比如我们在bash中使用set -x之后的跟踪提示就是这个提示符显示的。
    `
    $ echo $PS1
    [u@h W]$
    $ echo $PS2
    >
    $ echo $PS3

    $ echo $PS4
    +
    $ PS2=”>>> ”
    $ echo $PS2
    >>>
    $ echo ‘hi
    >>> abc
    >>> d
    >>> ‘
    hi
    abc
    d

    $
    `

  2. set命令除了可以通过-x参数设置为跟踪模式(xtrace)——跟踪各种语法的调用,并打印出每个命令的输出结果。

    还有几个参数/选项可以辅助调试:
    -n 可以用来检查bash的语法错误,并不会真正执行bash脚本。
    -e 让bash脚本命令执行错误的时候直接退出,而不是继续执行。这个功能在某些调试的场景下非常有用!
    -v 可视模式,它会在执行bash程序的时候将要执行的内容也打印出来,除此之外,并不改变bash执行的过程。

  3. 写好shell脚本的13个技巧
    https://mp.weixin.qq.com/s/f3xDHZ7dCQr7sHJ9KDvuyQ
    `
    1、提供–help标记
    2、检查所有命令的可用性
    3、独立于当前工作目录
    4、如何读取输入:环境变量 vs. 标记
    5、打印对系统执行的所有操作
    6、如果有必要,提供–silent选项
    7、重新开启显示
    8、用动画的方式显示进度
    9、用颜色编码输出
    10、出现错误立即退出脚本
    11、自己执行清理工作
    12、在退出时使用不同的错误码
    13、在结束时打印一个新行
    `

  4. 为什么 Shell 脚本不工作,语法之外的那些事儿
    http://tinylab.org/why-shell-scripts-fails/
    `
    2 程序搜索路径(Path)
    3 程序搜索类型(Type)
    4 检查执行权限
    5 指定正确的解释器
    6 跨平台的语法差异

    要让一个 Shell 程序正常工作,通常除了程序本身的语法之外,还需要注意程序运行的搜索路径、搜索类别,检查执行权限,指定正确的解释器,还需要注意平台差异。
    `

发表评论

电子邮件地址不会被公开。 必填项已用*标注