捕获远程ssh命令的输出失败

本·潘内尔

我试图在bash脚本中捕获远程执行命令的输出,以便该脚本可以对结果进行某些处理,并且对结果感到困惑:

$ COMMAND="ssh localhost \"echo 'hello'\""
$ OUTPUT=$($COMMAND)
bash: echo 'hello': command not found

使用反引号会产生稍微不同的结果:

$ `ssh localhost "echo 'hello'"`
-bash: hello: command not found

但是该命令在没有任何包装的情况下按预期运行:

$ ssh localhost "echo 'hello'"
hello

我怀疑我误解了有关如何执行这些命令的一些基本知识。我在这里做错了什么,还是有更好的方法来做?

安德里亚·科贝里尼(Andrea Corbellini)

问题

"..."执行以下操作时,不会评估引号():

$($COMMAND)

远程Bash看到的是两个参数:"echo'hello'",并非echo 'hello'您所期望的。

建议的解决方案:数组

我建议您使用的是数组:

COMMAND=( ssh localhost "echo 'hello'" )
OUTPUT=$( "${COMMAND[@]}" )

其中的单词(...)是数组的元素。在这种情况下,echo 'hello'可以看到一个元素:在赋值期间立即评估引号。然后,当您执行时"${COMMAND[@]}",所有元素都将作为原样传递为参数。

还有其他几种方法可以解决此问题,例如使用,eval以便对引号进行评估,但是以我的经验,使用数组是构建和执行命令的最安全,最简单的方法。使用数组可以很容易地防止shell注入攻击,防止不必要的扩展,防止在有空格的情况下破坏单词。唯一的缺点是数组并非在每个shell中都可用。

问题说明

原因是扩展(即$COMMAND)不评估引号。

这个简单的示例说明了这一点,在该示例中,我们每行打印一个参数:

$ COMMAND="ssh localhost \"echo 'hello'\""
$ for x in $COMMAND; do echo "$x"; done
ssh
localhost
"echo
'hello'"

通过使用数组代替:

$ COMMAND=( ssh localhost "echo 'hello'" )
$ for x in "${COMMAND[@]}"; do echo "$x"; done
ssh
localhost
echo 'hello'

对于数组,echo 'hello'在一行上(即,它是一个参数),而用一个简单的字符串代替,"echo并被'hello'"拆分。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章