我在 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)
您可以使用选项-p的logger命令通过本地syslog到自己的日志文件设置一个单独的设备和级别来写输出。
slm*_*slm 84
set -x我总是使用set -x和set +x。您可以将您想要查看它们发生的情况的区域包装起来,以提高/降低详细程度。
#!/bin/bash
set -x
..code to debug...
set +x
Run Code Online (Sandbox Code Playgroud)
此外,如果您已经完成了开发工作并且熟悉名称为 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)
导致这种类型的输出:

如果您需要更便携的东西,还有更旧的log4sh. 工作类似于log4bash,可在此处获得:
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
您可以通过下面链接的“_DEBUG.sh”脚本使用 Eclipse 和 Shelled 的组合环境。
默认情况下,Shelled 开发工具/bin/dash用作解释器。我将其更改为/bin/bash与 Web 上的大多数 shell 示例和我的环境具有更好的兼容性。
注意:您可以通过以下方式更改:Window -> Preference -> Shell Script -> Interpreters
Debugger 包具有使用_DEBUG.sh脚本进行脚本调试的步骤,基本上是(readme.txt):
- 创建 Shell 脚本项目: 文件->新建->其他-> Shell 脚本-> Shell 脚本项目向导。
- 创建一个 Bash 脚本文件:File -> New -> File。对于此示例,它将是
script.sh. 扩展名应该是“.sh”并且是必须的。- 将文件复制
_DEBUG.sh到项目文件夹。在文件顶部插入以下文本
script.sh:Run Code Online (Sandbox Code Playgroud). _DEBUG.sh如果文件是在 Microsoft Windows 中创建的,请确保执行File -> Convert Line Delimiters To -> Unix。
设置调试启动配置:运行->调试配置-> Bash 脚本...这里有 2 个字段需要设置:
a) “Bash 脚本:” - Eclipse 工作区中要调试的 Bash 脚本的路径。
e) “调试器端口:” 33333切换到调试透视图。启动调试会话。
script.sh从 bash shell启动。

这个 bash 调试器具有标准编程调试器的全部功能,例如:
Shelled(Shell 脚本编辑器)IDE(集成开发环境)有一个额外的好处,即在编写脚本时执行上下文检查、突出显示和缩进。如果它没有正确缩进,您可能会立即在那里标记/本地化许多错误。
然后还有其他 IDE 好处,例如:
小智 10
现在,有 VS Code Bash Debug。
https://marketplace.visualstudio.com/items?itemName=rogalmic.bash-debug
它具有“步进/步进/结束”功能,还显示每个变量的值。
只需使用:
#!/bin/bash -x
Run Code Online (Sandbox Code Playgroud)
外壳相同:
#!/bin/sh -x
Run Code Online (Sandbox Code Playgroud)
最近几年出现了一个很不错的资源:http : //shellcheck.net
它比普通 bash 向您展示的更多,让人们可以轻松找到那些讨厌的未闭合引号或大括号等。
只要确保你不要在网上粘贴敏感信息(ips、密码等)......(特别是因为它是 http,未加密)(我相信 shellcheck 也可以下载,但我不确定)