我对bash中的某些脚本有一些问题,涉及错误和意外行为。我想调查问题的原因,以便我可以应用修复程序。有什么办法可以让bash变成某种“调试模式”,以获得更多信息吗?

#1 楼

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


bash 4.1或更高版本:

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

exec 5> debug_output.txt
BASH_XTRACEFD="5"


请参阅:https://stackoverflow.com/a/25593226/3776858


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

PS4='$LINENO: '




如果可以访问logger命令,则您可以使用它通过带有时间戳,脚本名称和行号的系统日志来编写调试输出:

并通过本地syslog将输出写入其自己的日志文件的级别。

评论


-v也可以提供帮助(在执行时打印出每一行。可以与-x组合使用)。另请参阅:bashdb.sourceforge.net

–奥利维尔·杜拉克(Olivier Dulac)
2014-09-15 7:42



另一个很棒的资源是:shellcheck.net

–奥利维尔·杜拉克(Olivier Dulac)
15年5月30日在7:50

“ exec 5>”做什么?

– aggsol
17年1月25日在8:50

@aggsol:如果您使用BASH_XTRACEFD =“ 5”,则bash会在将set -x启用到文件描述符5时生成跟踪输出。exec 5>>(logger -t $ 0)将输出从文件描述符5重定向到logger命令。

– Cyrus
17年1月27日在16:15

只是想知道您能否在PS4中获得行号和Shell脚本路径或名称?

–尼克
17年7月28日在17:22

#2 楼

使用set -x


我总是使用set -xset +x。您可以包装要查看的区域,以提高/降低详细程度。

#!/bin/bash

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


log4bash

此外,如果您已经完成开发工作并且熟悉名称为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";


导致这种类型的输出:



log4sh

如果您需要更便携的东西,也可以选择较旧的log4sh。与log4bash相似的作品,可在此处找到:


https://sites.google.com/a/forestent.com/projects/log4sh


评论


在Ubuntu上,我的.bashrc中有别名say =“ spd-say”,它模仿其他发行版或OS X的say命令。

–门把手
2014年9月16日下午3:41

如果将set -vx与trap-trap read调试一起使用,将是一个很好的组合。这使您可以逐行查看结果

– Magnus Melwin
18年7月9日在6:10



#3 楼

有一个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


和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 楼

在大多数基于Bourne的shell(例如bash)中调试脚本的标准方法是在脚本顶部编写set -x。这将使bash在执行/执行的操作以及如何评估参数方面更加冗长。

-x  Print commands and their arguments as they are executed.


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

$ 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


在上面我们可以看到为什么由于某些单引号导致查找失败。

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

#5 楼

使用Eclipse

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


Eclipse Shelled插件:http ://sourceforge.net/projects/shelled/files/shelled/update/

bash调试器-仅适用于带壳的:http://sourceforge.net/projects/basheclipse/
<缺省情况下,带壳开发工具使用/bin/dash作为解释器。我将其更改为/bin/bash,以便与Web和我的环境上的大多数Shell示例具有更好的兼容性。

注意:您可以通过以下方法来更改它:Window-> Preference-> Shell Script->口译员

安装说明

Debugger软件包提供了使用_DEBUG.sh脚本进行脚本调试的步骤,该脚本基本上是(readme.txt):



创建Shell脚本项目:文件->新建->其他-> Shell脚本-> Shell脚本项目向导。
创建Bash脚本文件:文件->新建->文件。对于此示例,它将为script.sh。扩展名应为“ .sh”,并且必须为

将文件_DEBUG.sh复制到项目文件夹。

将以下文本插入文件script.sh的顶部:

. _DEBUG.sh


如果文件是在Microsoft Windows中创建的,请确保执行文件->将行定界符转换为-> Unix。

设置调试启动配置:运行->调试配置-> Bash脚本...在此处设置2个字段


a)“ Bash脚本:”-Eclipse工作空间中的路径到Bash脚本
进行调试。 e)“调试器端口:” 33333

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



bash调试UI



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


断点切换
单步操作
步入,步出,步移功能和子例程
在脚本运行时随时检查代码或变量<
Shelled(Shell脚本编辑器)IDE(集成开发环境)具有额外的优势,可以在编写脚本时执行上下文检查,突出显示和缩进。如果缩进不正确,您可能会立即在其中标记/本地出现许多错误。

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


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


评论


酷提示。很高兴知道Bash可以像这样调试。

–slm♦
2014-09-16的1:54

#6 楼

近年来,出现了一个很棒的资源:http://shellcheck.net

它比常规bash显示的内容更多,使您可以轻松找到那些讨厌的未封闭引号或大括号等。

请确保您不要通过网络粘贴敏感信息(ips,密码等)...(尤其是http,未加密)(我相信shellcheck也可以下载,但是我不确定)

#7 楼

如今,有了VS Code Bash调试程序。

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

它具有'Step in / out / over”,并显示每个变量的值。



评论


这个答案没有在正确的背景下解决这个问题;假定命令行,因为未提及IDE

–qodeninja
19/09/12'2:54

#8 楼

只需使用:

#!/bin/bash -x


外壳相同:

#!/bin/sh -x