我能在shell脚本中设置断点吗?

6

有没有一种方法可以暂停 shell 脚本的执行,以检查环境状态或执行随机命令?

3个回答

3

aliaseval 结合使用可以在调用上下文中实现基本的断点功能:

#!/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,请谨慎使用。


如果stdin/stdout/stderr没有被重定向,这种方法将不起作用。可能你可以保留当前的FD并在while循环期间将它们设置回TTY。 - psmears
@psmears 脚本只是为了给大家一个想法。还需要做很多工作才能在实际情况中使用。 - Philippe
好的,我只是想指出来,因为不了解这个限制的人可能会感到相当困惑 :) - psmears
1
@Philippe - 什么能让它更容易或更好?我并不是在纠结小节问题- 如果有一个实质性的原因,为什么它更好,我认为这是很重要的,应该在这里加以说明。我的第一倾向是使用函数,因为这是我的首选,但如果有一个实际上别名是更好的选择,则超越了个人偏好。 - mainmachine
1
@mainmachine 如果您使用函数,断点将在其自己的函数作用域中运行,而如果定义为别名,则在调用函数作用域中运行。这就是为什么我在我的答案中加入了“调用上下文”的原因。 - Philippe
显示剩余3条评论

1
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命令。

这可能对您有所帮助:https://www.baeldung.com/linux/debug-bash-script - SiKing

0

有一些解决方案,例如bash-debug。 对我来说可行的一个简单解决方案是交互式 shell。 通过添加三行代码,您可以按如下方式检查和更改变量:

假设您有脚本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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接