我有一个执行约20条命令的bash脚本,出于调试目的,我发现自己在输出中滚动了很多。 不幸的是,bash不能告诉我输出的哪一部分是什么命令的一部分。 当我在脚本中使用“ set -x”时,它至少会打印一些有关其刚刚执行的内容的信息,但我真的不喜欢它生成的输出。
例如,如果我有此脚本:
#!/bin/bash
set -x
echo "foo"
if [ "$ASD" == "QWE" ] ; then
echo "bar"
fi
我希望输出是这样的:
回显“ foo”
foo
回显“栏”
酒吧
或者也许:
回显“ foo”
foo
if [“” value_of_ASD“ ==” QWE“];然后
回显“栏”
酒吧
fi
与其以粗体显示命令,还可以用颜色突出显示。但是我不仅想在命令前加上“ +”字符,而且我也不希望if语句显示为'[' value_of_ASD == QWE ']'
。
我如何用bash做到这一点?
此刻输出如下所示:
+ echo foo
foo
+ '[' value_of_ASD == QWE ']'
+ echo bar
bar
编辑:
我的一个想法是编写一个脚本,该脚本将在主脚本的开始处提供,然后让源脚本解析主脚本。像这样:
source_me.sh
#!/bin/bash
SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/$(basename $0)"
FORMAT_SET_BOLD='\033[0;1m'
FORMAT_RESET='\033[0m'
cat $SCRIPT_PATH | tail -n "+$START_LINE" | while read line; do
printf "${FORMAT_SET_BOLD}${line}${FORMAT_RESET}\n"
eval "${line}"
done
exit 0;
main.sh
#!/bin/bash
START_LINE=$((LINENO+1)) source ./source_me.sh
echo "Foo"
echo "Bar"
echo "+Hello"
在这种情况下的输出是:
回显“ Foo”
富
回显“酒吧”
酒吧
回声“ +你好”
+你好
但是,如果我使用遍及多行的更复杂的代码(例如语句,循环等),则此方法将失败:
#!/bin/bash
START_LINE=$((LINENO+1)) source ./source_me.sh
echo "Foo"
if [ "$FOOBAR" == "" ] ; then
echo "Bar"
fi
echo "+Hello"
在这种情况下,我得到:
回显“ Foo”
富if [“ $ FOOBAR” ==“”];然后
./source_me.sh:eval:第9行:语法错误:文件意外结束
回显“酒吧”
酒吧
fi
./source_me.sh:eval:第8行:意外标记'fi'附近的语法错误
./source_me.sh:评估:第8行:“ fi”回显“ +你好”
+你好
答案 0 :(得分:2)
您可以通过设置+
将PS4
更改为所需的字符串,例如:
PS4="# "; set -x
答案 1 :(得分:1)
请注意,set -x
不了解您的终端,这是发送正确的字符以创建粗体或彩色文本所必需的。
如果可以通过单个文件句柄捕获所有输出,则可以使用管道来实现:
$ /path/to/your/script 2>&1 | sed "/^+ /s/.*/$(tput bold)&$(tput sgr0)/"
您可能想man tput
来获取有关我们用于获取粗体字的工具的更多信息。
此方法的可行性取决于我对您的环境不了解的许多因素。 YMMV,可能包含坚果。
注意:
您可能会认为最好用这样的一行单独捕获stderr:
$ /path/to/your/script 2> >(sed "/^+ /s/.*/$(tput bold)&$(tput sgr0)/")
A,这并不一致,因为通过脚本传递的stderr可能不会在随后的 stdout之前提交给终端。还要注意,该解决方案由于使用了进程替换,因此是一种bashism,不能移植到POSIX。
答案 2 :(得分:1)
我想用一些我认为值得单独回答的例子来扩展rubo77's answer:
因此,基本示例是将PS4
设置为某些纯文本,例如:
PS4="# "; set -x
这将导致:
但是由于可以使用特殊字符和ANSI转义码,因此可以在每个新命令之前添加新行,并以彩色打印前缀,例如:
PS4="\n\033[1;33m>>>\033[0m "; set -x
结果:
最后,您可以使命令前缀每次使用时都调用其他程序 ,您可以使用它们添加时间戳,例如:
# yes, there have to be single quotes below, not double!
PS4='\033[1;34m$(date +%H:%M:%S)\033[0m '; set -x
结果:
答案 3 :(得分:0)
您要寻找的是set -v
。
-v打印出解释器刚刚读取的行。
-x打印出解释器刚刚读取的行的后解析结果。
文件x
:
set -vx
foo=1
echo $foo
set +vx
执行中:
$: . x
foo=1
++ foo=1
echo $foo
++ echo 1
1
set +vx
++ set +vx