如何在 Linux 或 UNIX 下调试 Bash Shell 脚本
来自我的邮箱:我编写了一个小型 hello world 脚本。如何调试在 Linux 或类 Unix 系统上运行的 bash shell 脚本?
这是新系统管理员或 Linux/UNIX 用户最常问的问题。Shell 脚本调试可能是一项繁琐的工作(读起来并不容易)。有多种方法可以调试 shell 脚本。
您需要将-x或-v参数传递给 bash shell 来遍历脚本中的每一行。
让我们看看如何使用各种方法调试在 Linux 和 Unix 上运行的 bash 脚本。
使用-x选项调试 bash shell 脚本
运行带选项的 shell 脚本-x。语法为:
$ bash -x script-name
$ bash -x domains.sh
使用 set 内置命令
Bash shell 提供调试选项,可以使用 set 命令打开或关闭:
- set -x:显示执行时的命令及其参数。
- set -v:在读取 shell 输入行时显示它们。
示例
您可以在 shell 脚本中使用以上两个命令:
#!/bin/bash clear # turn on debug mode set -x for f in * do file $f done # turn OFF debug mode set +x ls # more commands
#!/bin/bash
您可以使用以下代码(用于调试)替换标准 Shebang 行:
#!/bin/bash -xv
使用智能DEBUG功能
首先,添加一个名为 _DEBUG 的特殊变量。当您需要调试脚本时,请将 _DEBUG 设置为“on”:
_DEBUG="on"
将以下函数放在脚本的开头:
function DEBUG() { [ "$_DEBUG" == "on" ] && $@ }
现在,无论您需要调试什么,只需使用 DEBUG 函数即可,如下所示:
DEBUG echo "File is $filename"
或
DEBUG set -x
Cmd1
Cmd2
DEBUG set +x
调试完成后(在将脚本移至生产之前),将 _DEBUG 设置为“off”。无需删除调试行。
_DEBUG="off" # set to anything but not to 'on'
示例脚本:
#!/bin/bash _DEBUG="on" function DEBUG() { [ "$_DEBUG" == "on" ] && $@ } DEBUG echo 'Reading files' for i in * do grep 'something' $i > /dev/null [ $? -eq 0 ] && echo "Found in $i file" done DEBUG set -x a=2 b=3 c=$(( $a + $b )) DEBUG set +x echo "$a + $b = $c"
保存并关闭文件。运行 bash 脚本如下:
$ ./script.sh
输出:
Reading files Found in xyz.txt file + a=2 + b=3 + c=5 + DEBUG set +x + '[' on == on ']' + set +x 2 + 3 = 5
现在将 DEBUG 设置为关闭(您需要编辑文件):
$ _DEBUG="off" ./script.sh
运行脚本:
输出:
$ export _DEBUG="off"
$ ./script.sh
Found in xyz.txt file 2 + 3 = 5
以上是一种简单但非常有效的技巧。您还可以尝试使用 DEBUG 作为别名而不是函数。
调试常见的 Bash Shell 脚本错误
Bash 或 sh 或 ksh 在屏幕上显示各种错误消息,并且在许多情况下错误消息可能不提供详细信息。
跳过对文件应用执行权限
当你编写第一个 hello world bash shell 脚本时,你可能会收到如下错误:
bash: ./hello.sh: Permission denied
使用 chmod 命令设置权限:
$ chmod +x hello.sh
$ ./hello.sh
$ bash hello.sh
文件结束意外错误
如果您收到文件结束意外错误消息,请打开脚本文件并确保它有开始和结束引号。在此示例中,echo 语句有开始引号但没有结束引号:
#!/bin/bash ... .... echo 'Error: File not found ^^^^^^^ missing quote
还要确保检查是否缺少括号和大括号({}):
#!/bin/bash ..... [ ! -d $DIRNAME ] && { echo "Error: Chroot dir not found"; exit 1; ^^^^^^^^^^^^^ missing brace } ...
缺少关键词,例如 fi、esac、;; 等。
如果您遗漏了结尾关键字(例如 fi 或 ;;),您将收到错误,例如“xxx 意外”。因此,请确保所有嵌套的 if 和 case 语句都以正确的关键字结尾。有关语法要求,请参阅 bash 手册页。在此示例中,缺少 fi:
#!/bin/bash echo "Starting..." .... if [ $1 -eq 10 ] then if [ $2 -eq 100 ] then echo "Do something" fi for f in $files do echo $f done # note fi is missing
在 Windows 或 Unix 系统上移动或编辑 shell 脚本
不要在 Linux/Unix 上创建脚本并移至 Windows。另一个问题是在 Windows 10 上编辑 bash shell 脚本并移动/上传到 Unix 服务器。这将导致由于回车符 (DOS CR-LF) 而导致命令未找到的错误。您可以使用以下语法将 DOS 换行符 CR-LF 转换为 Unix/Linux 格式:
$ dos2unix my-script.sh
技巧 1 – 将调试消息发送到 stderr
标准错误是默认的错误输出设备,用于写入所有系统错误消息。因此,将消息发送到默认错误设备是一个好主意:
# Write error to stdout echo "Error: $1 file not found" # # Write error to stderr (note 1>&2 at the end of echo command) # echo "Error: $1 file not found" 1>&2
技巧 2 – 使用 vim 文本编辑器时打开语法高亮
大多数现代文本编辑器都允许您设置语法突出显示选项。这对于检测语法和防止常见错误(例如打开或关闭引号)非常有用。您可以用不同的颜色查看 bash 脚本。此功能简化了在 shell 脚本中编写结构,并且语法错误在视觉上是不同的。突出显示不会影响文本本身的含义;它只为您而设。在此示例中,vim 语法突出显示用于我的 bash 脚本:
图 01:使用 vim 文本编辑器突出显示 Bash shell 脚本语法
技巧 3 – 使用 shellcheck 检查脚本
ShellCheck 是一个静态分析 shell 脚本的工具。你可以使用它来查找 shell 脚本中的错误。它是用 Haskell 编写的。你可以使用此工具找到 bash/sh shell 脚本的警告和建议。让我们看看如何在 Linux 或类 Unix 系统上安装和使用 ShellCheck 来增强你的 shell 脚本,避免错误并提高工作效率。