如何debugging一个bash脚本?
有没有什么办法来debugging一个bash脚本? 例如,打印某种执行日志,如“呼叫线路1”,“呼叫线路2”等
sh -x script [arg1 ...] bash -x script [arg1 ...]
这些给你一些正在执行的内容。 (另请参阅答案底部的“澄清”部分。)
有时候,您需要控制脚本中的debugging。 在这种情况下,正如Cheeto 提醒我的那样,您可以使用:
set -x
这将打开debugging。 然后您可以再次closures它:
set +x
(你可以通过分析$-
(当前的标志,找出当前的跟踪状态)。
另外,shell通常为'不执行'提供选项' -n
','verbose'模式提供' -v
'选项; 您可以结合使用这些参数来查看shell是否认为它可以执行您的脚本 – 偶尔有用的,如果您有不平衡的报价。
有争论说,Bash中的' -x
'选项与其他shell不同(请参阅注释)。 Bash手册说:
-
-X
打印一条简单的命令,
for
命令,case
命令,select
命令,以及for
命令及其参数或关联的单词列表被展开之后以及在执行之前的算术。PS4
variables的值被扩展,结果值被打印在命令及其扩展参数之前。
这似乎并不表示不同的行为。 在手册中我没有看到任何其他相关的“ -x
”的引用。 它没有描述启动顺序的差异。
说明 :在典型的Linux系统上,' /bin/sh
'是' /bin/bash
'的符号链接(或者Bash可执行文件的位置),这两个命令行实现了运行脚本的等效效果与执行追踪。 在其他系统上(例如Solaris和更现代的Linux版本), /bin/sh
不是Bash,两个命令行会给出(稍微)不同的结果。 最值得注意的是,' /bin/sh
'会被Bash中的构造所混淆,它根本不能识别。 (在Solaris上, /bin/sh
是一个Bourne shell;在现代Linux上,它有时是Dash – 一个更小,更严格的POSIX-only shell)。当被这样的名字调用时,'shebang'行(' #!/bin/bash
' '#!/bin/sh
')对文件内容的解释没有任何影响。
Bash手册有一个关于Bash POSIX模式的部分,与这个答案的一个长期但错误的版本(也见下面的注释)相反,详细地描述了“作为sh
调用的bash”和调用的bash之间的区别作为bash
'。
在debugging(Bash)shell脚本时,使用-x
选项在shebang行中命名的shell将是明智和理智的 – 甚至是必要的。 否则,从运行脚本进行debugging时,您可能会(将?)得到不同的行为。
我用下面的方法来debugging我的脚本。
如果任何外部程序返回非零退出状态,则set -e
使脚本立即停止。 如果你的脚本试图处理所有的错误情况,并且不应该这样做,那么这很有用。
上面提到了set -x
,它肯定是所有debugging方法中最有用的。
set -n
也可能是有用的,如果你想检查你的脚本的语法错误。
strace
也是有用的,看看发生了什么事情。 如果你没有自己写脚本,特别有用。
这个答案是有效的和有用的: https : //stackoverflow.com/a/951352
但是,我发现“标准”脚本debugging方法效率低,不直观,而且很难使用。 对于那些习惯于使用复杂的GUIdebugging器的人来说,这些解决scheme并不令人满意。
我所做的是使用DDD和bashdb的组合。 前者执行后者,后者执行你的脚本。 这提供了一个多窗口的用户界面,能够在上下文中遍历代码并查看variables,堆栈等,而不需要经常的精力来维护头脑中的上下文或者重新列出源代码。
有关于在这里设置的指导: http : //ubuntuforums.org/showthread.php?t=660223
你也可以在脚本中写“set -x”。
我发现shellcheck工具,可能有些人觉得它有趣https://github.com/koalaman/shellcheck
一个小例子:
$ cat test.sh ARRAY=("hello there" world) for x in $ARRAY; do echo $x done $ shellcheck test.sh In test.sh line 3: for x in $ARRAY; do ^-- SC2128: Expanding an array without an index only gives the first element.
修复这个错误,先试试…
$ cat test.sh ARRAY=("hello there" world) for x in ${ARRAY[@]}; do echo $x done $ shellcheck test.sh In test.sh line 3: for x in ${ARRAY[@]}; do ^-- SC2068: Double quote array expansions, otherwise they're like $* and break on spaces.
让我们再试一次…
$ cat test.sh ARRAY=("hello there" world) for x in "${ARRAY[@]}"; do echo $x done $ shellcheck test.sh
现在找!
这只是一个小例子。
我build了一个Bashdebugging器。 只要试一试。 我希望它会帮助https://sourceforge.net/projects/bashdebugingbash
我想你可以试试这个Bashdebugging器: http : //bashdb.sourceforge.net/ 。
设置+ x = @ECHO OFF,设置-x = @ECHO ON。
你可以添加-xv
选项到标准的Shebang中,如下所示:
#!/bin/bash -xv
-x
:在执行时显示命令及其参数。
-v
:在读取shell时显示shellinput行。
ltrace
是另一个类似于strace
Linux实用程序。 但是, ltrace
列出了在可执行文件或正在运行的进程中调用的所有库调用。 它的名字本身来自图书馆电话追踪。 例如:
ltrace ./executable <parameters> ltrace -p <PID>
资源
一些技巧来debuggingbash脚本:
使用set -[nvx]
此外
set -x
和
set +x
停止转储。
我想谈谈set -v
旺旺转储为较小的开发输出。
bash <<<$'set -x\nfor i in {0..9};do\n\techo $i\n\tdone\nset +x' 2>&1 >/dev/null|wc -l 21 for arg in xvn nx nv nvx;do echo "- opts: $arg" bash 2> >(wc -l|sed s/^/stderr:/) > >(wc -l|sed s/^/stdout:/) <<eof set -$arg for i in {0..9};do echo $i done set +$arg echo Done. eof sleep .02 done - opts: x stdout:11 stderr:21 - opts: v stdout:11 stderr:4 - opts: n stdout:0 stderr:0 - opts: nx stdout:0 stderr:0 - opts: nv stdout:0 stderr:5 - opts: nvx stdout:0 stderr:5
转储variables或即时追踪
为了testing一些variables,我使用了这个:
bash <(sed '18ideclare >&2 -p var1 var2' myscript.sh) args
添加:
declare >&2 -p var1 var2
在第18行并运行结果脚本(带有参数 ),而不必编辑它们。
当然,这可以用于添加set [+-][nvx]
:
bash <(sed '18s/$/\ndeclare -p v1 v2 >\&2/;22s/^/set -x\n/;26s/^/set +x\n/' myscript) args
将在第18行之后添加declare -p v1 v2 >&2
,在第22行之前set -x
,并在第26行之前set +x
。
小样本:
bash <(sed '2,3s/$/\ndeclare -p LINENO i v2 >\&2/;5s/^/set -x\n/;7s/^/set +x\n/' <( seq -f 'echo $@, $((i=%g))' 1 8)) arg1 arg2 arg1 arg2, 1 arg1 arg2, 2 declare -i LINENO="3" declare -- i="2" /dev/fd/63: line 3: declare: v2: not found arg1 arg2, 3 declare -i LINENO="5" declare -- i="3" /dev/fd/63: line 5: declare: v2: not found arg1 arg2, 4 + echo arg1 arg2, 5 arg1 arg2, 5 + echo arg1 arg2, 6 arg1 arg2, 6 + set +x arg1 arg2, 7 arg1 arg2, 8
注意:关心$LINENO
将受到dynamic修改的影响!
(要查看生成的脚本没有执行,只需删除bash <(
和) arg1 arg2
)
一步一步,执行时间
看看我的关于如何configurationbash脚本的答案
安装VSCode ,然后添加bashdebugging扩展,并准备好在可视模式下进行debugging。 看到这里在行动。
使用eclipse插件shelled和basheclipse。
https://sourceforge.net/projects/shelled/?source=directory https://sourceforge.net/projects/basheclipse/?source=directory
对于shelled:下载zip并通过帮助将其导入eclipse – >安装新的软件:local archive for basheclipse:将jar复制到eclipse的dropins目录下
按照提供的步骤https://sourceforge.net/projects/basheclipse/files/?source=navbar
我在http://dietrichschroff.blogspot.de/2017/07/bash-enabling-eclipse-for-bash.html上写了很多截图的教程;
通过shell的全局变化对shell脚本进行日志logging有很多细节。 我们可以在shell脚本中模拟类似的日志logging: http : //www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html
这篇文章详细介绍了INFO,DEBUG,ERROR等日志级别。 跟踪细节,如脚本input,脚本退出,函数input,函数退出。
示例日志: