调试模式

Bash 内置了调试选项,可以在执行脚本时显示详细信息。最常用的是 -x 选项,它会打印每条执行的命令,帮助追踪脚本的执行流程。

启用调试模式

命令行参数

运行脚本时添加调试选项:

bash -x script.sh
bash -v script.sh
bash -xv script.sh

常用选项:

选项含义
-x打印执行的命令(xtrace)
-v打印脚本源码(verbose)
-n只检查语法,不执行

脚本内启用

在脚本开头添加 shebang 参数:

#!/bin/bash -x

或在脚本中使用 set 命令:

#!/bin/bash
set -x

-x 选项详解

-x 选项会在执行每条命令前打印该命令,前面加上 + 号:

#!/bin/bash
set -x

name="张三"
echo "你好,$name"

运行结果:

+ name=张三
+ echo '你好,张三'
你好,张三

可以看到变量赋值和命令执行的过程。

调试特定代码段

可以只对部分代码启用调试:

#!/bin/bash

echo "开始执行"

set -x
# 需要调试的代码
for i in 1 2 3; do
    echo $i
done
set +x

echo "继续执行"

set +x 关闭调试模式。

-v 选项详解

-v 选项打印脚本的源代码行,在执行前显示:

#!/bin/bash
set -v

name="张三"
echo "你好,$name"

运行结果:

name="张三"
echo "你好,$name"
你好,张三

-x 和 -v 的区别

  • -v:显示脚本源码,执行前打印
  • -x:显示执行的命令,执行前打印,变量已展开

组合使用:

bash -xv script.sh

可以同时看到源码和执行情况。

-n 选项

-n 只检查语法错误,不执行脚本:

bash -n script.sh

适合在提交代码前检查语法。

自定义调试输出

PS4 变量

PS4 变量定义 -x 模式下的提示符,默认是 +

PS4='+ ${BASH_SOURCE}:${LINENO}: '
bash -x script.sh

输出会显示文件名和行号:

+ script.sh:5: name=张三
+ script.sh:6: echo '你好,张三'

更详细的设置:

PS4='+ ${BASH_SOURCE:-}:${FUNCNAME[0]:-}:${LINENO}: '

调试函数

debug() {
    if [[ $DEBUG -eq 1 ]]; then
        echo "[DEBUG] $*" >&2
    fi
}

debug "变量值:$var"

通过设置 DEBUG=1 启用调试输出。

使用 trap 调试

trap 可以在每条命令执行前触发:

#!/bin/bash

trap 'echo "执行第 $LINENO 行: $BASH_COMMAND"' DEBUG

name="张三"
echo "你好,$name"

运行结果:

执行第 5 行: name=张三
执行第 6 行: echo "你好,$name"
你好,张三

调试技巧

打印变量值

echo "变量值:$var"
printf "数组内容:%s\n" "${arr[@]}"
declare -p var  # 显示变量声明

检查命令执行结果

cmd
echo "退出状态:$?"

使用 shellcheck

shellcheck 是静态分析工具,可以检查脚本中的问题:

shellcheck script.sh

它会指出潜在的语法错误、不规范的写法、可能的 bug。

调试循环

for i in {1..10}; do
    echo "循环第 $i 次"
    # 循环体
done

调试函数

my_func() {
    echo "进入函数,参数:$@"
    # 函数体
    echo "函数返回:$?"
}

实用示例

带调试开关的脚本

#!/bin/bash

DEBUG=${DEBUG:-0}

log() {
    if [[ $DEBUG -eq 1 ]]; then
        echo "[$(date '+%H:%M:%S')] $*"
    fi
}

log "开始执行"
log "变量值:$var"

运行:

DEBUG=1 ./script.sh

调试模式输出到文件

#!/bin/bash

exec 5> debug.log
BASH_XTRACEFD=5
set -x

# 脚本内容

调试输出会写入 debug.log 文件。

小结

  • bash -x script.sh 打印执行的命令
  • bash -v script.sh 打印脚本源码
  • bash -n script.sh 只检查语法
  • set -xset +x 控制调试范围
  • PS4 自定义调试提示符
  • trap DEBUG 可以在每行执行前触发
  • shellcheck 是静态分析的好帮手