我可以把一个断点在shell脚本?



是否有办法暂停shell脚本的执行以检查环境的状态或执行随机命令?

alias结合eval提供了调用上下文中断点的基本功能:

#!/bin/bash
shopt -s expand_aliases
alias breakpoint='
while read -p"Debugging(Ctrl-d to exit)> " debugging_line
do
eval "$debugging_line"
done'
f(){
local var=1
breakpoint
echo $'n'"After breakpoint, var=$var"
}
f

在断点处,可以输入

echo $var

紧随其后
var=2

然后按Ctrl-d退出断点。

由于while循环中有eval,请谨慎使用

Bash或shell脚本不具有像Java、Python等其他编程语言那样的调试功能。

我们可以将echo "VAR_NAME=$VAR_NAME"命令放在我们想要记录变量值的代码中。

另外,一个更灵活的解决方案是把这段代码放在我们要调试的shell脚本的开头:
function BREAKPOINT() {
BREAKPOINT_NAME=$1
echo "Enter breakpoint $BREAKPOINT_NAME"
set +e
/bin/bash
BREAKPOINT_EXIT_CODE=$?
set -e
if [[ $BREAKPOINT_EXIT_CODE -eq 0 ]]; then
echo "Continue after breakpoint $BREAKPOINT_NAME"
else
echo "Terminate after breakpoint $BREAKPOINT_NAME"
exit $BREAKPOINT_EXIT_CODE
fi
}
export -f BREAKPOINT

,然后,在我们需要中断的代码行,我们像这样调用这个函数:

# some shell script here
BREAKPOINT MyBreakPoint
# and some other shell script here

那么BREAKPOINT函数将记录一些输出,然后启动/bin/bash,我们可以运行任何echo或其他我们想要的shell命令。当我们想要继续运行shell脚本的其余部分时(释放断点),我们只需要执行exit命令。如果我们需要终止脚本执行,我们可以运行exit 1命令。

存在像bash-debug这样的解决方案。对我来说,穷人的解决方案是交互式外壳。通过添加三行代码,您可以内省和更改变量,如下所示:

让我们假设,您有脚本test.bash

A=FOO
export B=BAR
echo $A
echo $B
$ test.bash
FOO
BAR

如果您在第3行添加交互式shell,您可以查看并检查之前导出的变量:

A=FOO
export B=BAR
bash -c "$SHELL"
echo $A
echo $B
$ test.bash
$ echo $A
$ echo $B
BAR
$ exit
FOO
BAR

如果你想在你的交互式shell中看到所有的变量,你必须在你的脚本的序言中添加set -a,这样所有的变量和函数都被导出:

set -a
A=FOO
export B=BAR
bash -c "$SHELL"
echo $A
echo $B
$ test.bash
$ echo $A
FOO
$ echo $B
BAR
$ exit
FOO
BAR

注意,您不能更改交互式shell中的变量。对我来说,唯一的解决方案是提供一个额外的变量脚本,它将在交互式shell

之后提供。
set -a
A=FOO
export B=BAR
bash -c "$SHELL"
source /tmp/var
echo $A
echo $B
$ test.bash
$ echo "export A=alice" > /tmp/var
$ echo "export B=bob" >> /tmp/var
$ exit
alice
bob