为什么应该避免在 Bash 中使用 eval,以及应该用什么代替?


eval 是 Bash shell 的一个内置命令,它将它的参数连接成一个单一的字符串。然后它用空格连接这些参数,然后执行该字符串作为 bash 命令。下面是一个它如何工作的例子。

eval 示例

在下面的例子中,我们取一个包含一些 Unix 命令的字符串,然后对其应用 eval。

$ var="echo n"
$ echo $var
$ eval $var

运行以上代码得到以下结果:

echo n
n

正如你所看到的,当应用 eval 时,变量会展开并被执行为命令,不再仅仅作为一个字符串。

eval 的问题

当我们创建一些包含函数的变量或脚本时,我们可以将一些值推送到变量或函数中,这些值可能存在潜在的危险。例如,删除文件命令可以传递给接受用户参数的脚本。脚本的所有者将具有删除文件的权限,但调用脚本的用户没有。

考虑以下脚本,我们调用一个在其内部包含 eval 函数的函数。

Printa_rray() {
   in_array=$1
   eval echo "\"The first vale in the array is \${$in_array[0]}\""
}
fruits=(apple, orange, grapes,berry)
print_array fruits

运行以上代码得到以下结果:

The first vale in the array is apple.

以上结果是预期的。但想象一下,用户使用以下参数调用该函数。

print_array() {
   in_array=$1
   eval echo "\"The first vale in the array is \${$in_array[0]}\""
}
fruits=(apple, orange, grapes,berry)
print_array 'x}"; cal; #'

运行以上代码得到以下结果:

The first vale in the array is
December 2019
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

正如你所看到的,由于脚本中存在 eval 函数,用户能够完全绕过脚本的预期功能。如果用户将像 rm *.* 这样的命令作为脚本参数传递,这可能会变得危险。

eval 的替代方案

由于上述影响,有一些可用的 eval 替代方案,可以使用它们,不会造成这样的安全威胁。

使用 token_quote 使 eval 更安全。

更新于: 2020年1月3日

1K+ 阅读量

开启你的 职业生涯

通过完成课程获得认证

开始学习
广告