如何调试 bash 脚本?

如何调试 bash 脚本?

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

答案1

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


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

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

exec 5> debug_output.txt
BASH_XTRACEFD="5"

看:https://stackoverflow.com/a/25593226/3776858


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

PS4='$LINENO: '


如果您有权访问logger命令,那么您可以使用它通过系统日志写入调试输出,其中包含时间戳、脚本名称和行号:

#!/bin/bash

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

# Place your code here

您可以使用命令选项-plogger设置单独的设施和级别,以通过本地系统日志将输出写入其自己的日志文件。

答案2

使用set -x

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

#!/bin/bash

set -x
..code to debug...
set +x

日志4bash

另外,如果您已经完成了开发工作并且熟悉名为 log4j、log4perl 等的记录器的风格,那么您可能想要使用日志4bash

摘抄

让我们面对现实吧——普通的旧回声并不能解决问题。 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";

产生这种类型的输出:

    SS1

日志4sh

如果您需要更便携的东西,还有较旧的log4sh.与 类似log4bash,可在此处获取:

答案3

有一个 bash 调试器,bash数据库,这是许多发行版上的可安装包。它使用 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

与 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

这不是我们想要的!我们再看一下参数扩展。

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

好的,这有效。让我们设置newf为正确的值。

bashdb<10> eval newf=${f/%JPG/jpg}
$? is 0
bashdb<11> print $f $newf
2ndJPG.JPG 2ndJPG.jpg

看起来不错。继续剧本。

bashdb<12> next
Debugged program terminated normally. Use q to quit or R to restart.
$ ls
1st.jpg  2ndJPG.jpg

答案4

使用Eclipse

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

切换外壳

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

笔记:您可以通过以下方式更改此设置:窗户->偏爱->外壳脚本->口译员

设置说明

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

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

    . _DEBUG.sh
    
  5. 如果该文件是在 Microsoft Windows 中创建的,请务必执行文件->将行分隔符转换为->Unix

  6. 设置调试启动配置:跑步->调试配置->bash 脚本...这里有2个字段需要设置:

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

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

bash 调试用户界面

在此输入图像描述

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

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

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

然后还有其他 IDE 优势例如:

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

相关内容