【发布时间】:2015-07-07 11:50:55
【问题描述】:
考虑以下代码:
#!/bin/bash -x
VAR='1 2 3'
bash -c "echo "\$$VAR""
eval "echo "\$$VAR""
bash -c "echo \"\$$VAR\""
eval "echo \"\$$VAR\""
哪些输出:
+ VAR='1 2 3'
+ bash -c 'echo $1' 2 3
3
+ eval 'echo $1' 2 3
++ echo 2 3
2 3
+ bash -c 'echo "$1 2 3"'
2 3
+ eval 'echo "$1 2 3"'
++ echo ' 2 3'
2 3
eval 和 bash -c 似乎都以相同的方式解释代码,即 "echo "\$$VAR"" 到 'echo $1' 2 3 和 "echo \"\$$VAR\"" 到 'echo "$1 2 3"'。
我似乎注意到的唯一区别是bash -c 打开了一个子shell,因此结果与eval 不同。例如,在
bash -c 'echo $1' 2 3
2 和 3 是子外壳的位置参数。另一方面,在
eval 'echo $1' 2 3
它们只是echo 的另一个参数。
所以我的问题是,-c 选项(bash -c、sh -c 或其他 shell 的等效项)是安全使用还是像 eval 那样邪恶?
【问题讨论】:
-
安全用于什么用途?
-
@Marki555 用于命令执行
-
我相信它们在传递相同的输入时在功能上实际上是相同的。您需要非常小心地控制/清理可能作为命令运行的任何内容。主要区别在于为
bash -c生成的单独进程与eval不同,后者的成本可能更高,并且意味着变量不能从命令中“泄漏”回来。 -
一般来说,很多 bash 在 POSIX sh 上的扩展都是为了能够减少或消除
eval调用——参见赋值端的printf -v,${!varname}扩展结束,bash 4.3 名称变量等。在现代 bash 中,eval仍然有一个合法的用例是非常罕见的。 -
问题似乎不是关于避免运行
bash -c,而是关于运行bash -c从shell脚本。在一般情况下,bash -c没有任何问题,它传递了一个静态代码字符串,就像在该脚本是静态的、手写的、经过审查的代码时运行bash somescript没有任何问题一样;当-c的参数或脚本是机器生成的,没有特别小心时,任何一个都是危险的。