如何调试 bash 脚本?

Bra*_*iam 183 bash debugging

我在 bash 中遇到了一些关于错误和意外行为的脚本问题。我想调查问题的原因,以便我可以应用修复程序。有没有办法可以为 bash 开启某种“调试模式”,以获取更多信息?

Cyr*_*rus 178

使用bash -x ./script.sh或添加脚本set -x来启动 bash 脚本以查看调试输出。


bash4.1 或更高版本的附加功能:

如果要将调试输出写入单独的文件,请将其添加到脚本中:

exec 5> debug_output.txt
BASH_XTRACEFD="5"
Run Code Online (Sandbox Code Playgroud)

参见:https : //stackoverflow.com/a/25593226/3776858


如果您想查看行号,请添加以下内容:

PS4='$LINENO: '
Run Code Online (Sandbox Code Playgroud)


如果您有权访问logger命令,那么您可以使用它通过带有时间戳、脚本名称和行号的 syslog 编写调试输出:

#!/bin/bash

exec 5> >(logger -t $0)
BASH_XTRACEFD="5"
PS4='$LINENO: '
set -x

# Place your code here
Run Code Online (Sandbox Code Playgroud)

您可以使用选项-plogger命令通过本地syslog到自己的日志文件设置一个单独的设备和级别来写输出。

  • -v 也可以提供帮助(在执行时打印出每一行。可以与 -x 结合使用)。另见:http://bashdb.sourceforge.net/ (8认同)
  • 另一个很棒的资源是:http://shellcheck.net (4认同)
  • @aggsol:如果您使用`BASH_XTRACEFD="5"` bash 会将启用`set -x` 时生成的跟踪输出写入[文件描述符](https://en.wikipedia.org/wiki/File_descriptor) 5. ` exec 5> >(logger -t $0)` 将输出从文件描述符 5 重定向到 `logger` 命令。 (4认同)

slm*_*slm 84

使用 set -x

我总是使用set -xset +x。您可以将您想要查看它们发生的情况的区域包装起来,以提高/降低详细程度。

#!/bin/bash

set -x
..code to debug...
set +x
Run Code Online (Sandbox Code Playgroud)

日志4bash

此外,如果您已经完成了开发工作并且熟悉名称为 log4j、log4perl 等的记录器的样式,那么您可能想要使用log4bash

摘抄

让我们面对现实 - 普通的旧回声并没有削减它。log4bash 试图为 Bash 脚本提供更好的日志记录(即让 Bash 中的日志记录更少)。

从那里你可以在你的 Bash 脚本中做这样的事情:

#!/usr/bin/env bash
source log4bash.sh

log "This is regular log message... log and log_info do the same thing";

log_warning "Luke ... you turned off your targeting computer";
log_info "I have you now!";
log_success "You're all clear kid, now let's blow this thing and go home.";
log_error "One thing's for sure, we're all gonna be a lot thinner.";

# If you have figlet installed -- you'll see some big letters on the screen!
log_captains "What was in the captain's toilet?";

# If you have the "say" command (e.g. on a Mac)
log_speak "Resistance is futile";
Run Code Online (Sandbox Code Playgroud)

导致这种类型的输出:

    SS1

日志4sh

如果您需要更便携的东西,还有更旧的log4sh. 工作类似于log4bash,可在此处获得:

  • 如果与 trap - trap read debug 一起使用, set -vx 将是一个很好的组合。这允许您逐行跳过并查看结果 (2认同)

Mar*_*ick 38

有一个 bash 调试器bashdb,它是许多发行版上的可安装包。它使用 bash 的内置扩展调试模式 ( shopt -s extdebug)。它看起来很像 gdb;这是一个示例会话,以提供一些风味:

$ ls
1st.JPG  2ndJPG.JPG
$ cat ../foo.sh
for f in *.JPG
do
  newf=${f/JPG/jpg}
  mv $f $newf
done
$ bashdb ../foo.sh
(foo.sh:1):
1:      for f in *.JPG
bashdb<0> next
(foo.sh:3):
3:        newf=${f/JPG/jpg}
bashdb<1> next
(foo.sh:4):
4:        mv $f $newf
Run Code Online (Sandbox Code Playgroud)

与在 gdb 中一样,该语句即将执行之前显示。因此,我们可以检查变量以查看语句在执行之前会执行什么操作。

bashdb<2> print $f $newf
1st.JPG 1st.jpg
bashdb<3> next
(foo.sh:1):
1:      for f in *.JPG
bashdb<4> next
(foo.sh:3):
3:        newf=${f/JPG/jpg}
bashdb<5> next
(foo.sh:4):
4:        mv $f $newf
bashdb<6> print $f $newf
2ndJPG.JPG 2ndjpg.JPG
Run Code Online (Sandbox Code Playgroud)

那不是我们想要的!我们再来看看参数展开。

bashdb<7> print $f ${f/JPG/jpg}
2ndJPG.JPG 2ndjpg.JPG
bashdb<8> print $f ${f/JPG$/jpg}
2ndJPG.JPG 2ndJPG.JPG
bashdb<9> print $f ${f/%JPG/jpg}
2ndJPG.JPG 2ndJPG.jpg
Run Code Online (Sandbox Code Playgroud)

好的,那行得通。让我们设置newf为正确的值。

bashdb<10> eval newf=${f/%JPG/jpg}
$? is 0
bashdb<11> print $f $newf
2ndJPG.JPG 2ndJPG.jpg
Run Code Online (Sandbox Code Playgroud)

看起来挺好的。继续脚本。

bashdb<12> next
Debugged program terminated normally. Use q to quit or R to restart.
$ ls
1st.jpg  2ndJPG.jpg
Run Code Online (Sandbox Code Playgroud)


Bra*_*iam 19

在大多数基于 Bourne 的 shell(如 bash)中调试脚本的标准方法是set -x在脚本的顶部编写。这将使 bash 更加详细地说明正在完成/执行的内容以及如何评估参数。

-x  Print commands and their arguments as they are executed.
Run Code Online (Sandbox Code Playgroud)

这对解释器或内部脚本都很有用。例如:

$ find "$fileloc" -type f -prune "$filename" -print
+ find /var/adm/logs/morelogs -type f -prune '-name *.user' -print
find: unknown predicate '-name *.user'
$ find "$fileloc" -type f -prune $filename -print
+ find /var/adm/logs/morelogs -type f -prune -name '*.user' -print
find: '/var/adm/logs/morelogs': No such file or directory
Run Code Online (Sandbox Code Playgroud)

在上面我们可以看到为什么 find 由于一些单引号而失败。

要停用该功能,只需键入set +x


L. *_*mes 15

使用 Eclipse

您可以通过下面链接的“_DEBUG.sh”脚本使用 Eclipse 和 Shelled 的组合环境。

切换外壳

默认情况下,Shelled 开发工具/bin/dash用作解释器。我将其更改为/bin/bash与 Web 上的大多数 shell 示例和我的环境具有更好的兼容性。

注意:您可以通过以下方式更改:Window -> Preference -> Shell Script -> Interpreters

安装说明

Debugger 包具有使用_DEBUG.sh脚本进行脚本调试的步骤,基本上是(readme.txt):

  1. 创建 Shell 脚本项目: 文件->新建->其他-> Shell 脚本-> Shell 脚本项目向导
  2. 创建一个 Bash 脚本文件:File -> New -> File。对于此示例,它将是script.sh. 扩展名应该是“.sh”并且是必须的。
  3. 将文件复制_DEBUG.sh到项目文件夹。
  4. 在文件顶部插入以下文本script.sh

    . _DEBUG.sh
    
    Run Code Online (Sandbox Code Playgroud)
  5. 如果文件是在 Microsoft Windows 中创建的,请确保执行File -> Convert Line Delimiters To -> Unix

  6. 设置调试启动配置:运行->调试配置-> Bash 脚本...这里有 2 个字段需要设置:

    a) “Bash 脚本:” - Eclipse 工作区中要调试的 Bash 脚本的路径。
    e) “调试器端口:” 33333

  7. 切换到调试透视图。启动调试会话。script.sh从 bash shell启动。

bash 调试界面

在此处输入图片说明

这个 bash 调试器具有标准编程调试器的全部功能,例如:

  • 断点切换
  • 单步操作
  • 步进、步进、步进功能和子程序
  • 在脚本运行时随时检查代码或变量

Shelled(Shell 脚本编辑器)IDE(集成开发环境)有一个额外的好处,即在编写脚本时执行上下文检查、突出显示和缩进。如果它没有正确缩进,您可能会立即在那里标记/本地化许多错误。

然后还有其他 IDE 好处,例如:

  • TODO 任务列表
  • Mylyn 任务
  • 书签列表
  • 多窗口编辑
  • 环境的远程共享


小智 10

现在,有 VS Code Bash Debug。

https://marketplace.visualstudio.com/items?itemName=rogalmic.bash-debug

它具有“步进/步进/结束”功能,还显示每个变量的值。

VS Code Bash 调试截图


Ger*_*ery 9

只需使用:

#!/bin/bash -x
Run Code Online (Sandbox Code Playgroud)

外壳相同:

#!/bin/sh -x
Run Code Online (Sandbox Code Playgroud)


Oli*_*lac 9

最近几年出现了一个很不错的资源:http : //shellcheck.net

它比普通 bash 向您展示的更多,让人们可以轻松找到那些讨厌的未闭合引号或大括号等。

只要确保你不要在网上粘贴敏感信息(ips、密码等)......(特别是因为它是 http,未加密)(我相信 shellcheck 也可以下载,但我不确定)