为什么 eval "$BASH_COMMAND" 会崩溃 bash?

Why does eval "$BASH_COMMAND" crash bash?

如果你在终端里运行 eval "$BASH_COMMAND",它会崩溃,终端window会消失。我无法理解为什么这个特定命令会崩溃 bash

奇怪的是,当我运行echo "$BASH_COMMAND"时,出现了这样的情况:

$ echo "$BASH_COMMAND"
echo "$BASH_COMMAND"

另一件事是$BASH_COMMAND没有值:

"$BASH_COMMAND"
bash: "$BASH_COMMAND": command not found

$BASH_COMMAND 确实有一个值:当前正在执行的命令。这在 trap 处理程序等情况下很有用,因此处理程序可以找出陷阱触发时正在执行的命令。但是,当您将 $BASH_COMMAND 作为常规命令的一部分使用时,事情会变得奇怪、循环和混乱。让我们看看你给出的例子:

  • echo "$BASH_COMMAND"

    在此示例中,BASH_COMMAND 变量的值恰好是字符串 echo "$BASH_COMMAND",因此当 shell 解析命令行时,它扩展了变量引用,相当于:

    echo 'echo "$BASH_COMMAND"'
    

    注意:那里的单引号并不是命令的真正部分,它们只是我添加的内容,表示命令的那部分不应该进行变量扩展、双引号删除等。在真正的命令,这些不应该完成,因为 它们已经 完成了。无论如何,结果是按字面打印字符串,给出你看到的结果。

  • "$BASH_COMMAND"

    同样,BASH_COMMAND 的值恰好是字符串 "$BASH_COMMAND",因此展开后它等同于:

    '"$BASH_COMMAND"'
    

    ...并且没有该名称的命令,因此您会得到一个错误。

    (实际上,unix 文件名中允许使用引号和美元符号,因此您可以命名一个脚本并将其放在 PATH 中的某个位置,然后 是一个有效的命令名称。我不特别推荐这样做。)

  • eval "$BASH_COMMAND"

    这个比较复杂。 BASH_COMMAND的值是字符串eval "$BASH_COMMAND",所以展开后相当于:

    eval 'eval "$BASH_COMMAND"'
    

    但是 eval 命令所做的是将其参数 运行 作为 shell 命令,包括所有通常的解析。所以,它 运行 是命令:

    eval "$BASH_COMMAND"
    

    ...再次扩展 $BASH_COMMAND,导致:

    eval 'eval "$BASH_COMMAND"'
    

    ...这使得 eval 命令解析并且 运行:

    eval "$BASH_COMMAND"
    

    ...这个循环永远持续下去。或者更确切地说,它最终 运行 耗尽了一些资源(可能是堆栈 space),因为它试图跟踪这个不断扩展的东西。显然这会导致处理不当的崩溃。

    但无论细节如何,该命令都不可能起作用。它要求 shell 执行无限系列任务,并且无法成功结束。