【问题标题】:Capturing output of remote ssh command failing捕获远程 ssh 命令失败的输出
【发布时间】:2019-01-16 05:37:01
【问题描述】:

我试图在 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

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

【问题讨论】:

    标签: bash ssh


    【解决方案1】:

    问题

    报价 ("...") 在您这样做时不会被评估:

    $($COMMAND)
    

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

    建议的解决方案:数组

    在您的情况下,我建议使用数组:

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

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

    还有其他几种方法可以解决此问题,例如使用eval 以便评估引号,但根据我的经验,使用数组是构建和执行命令的最安全和最简单的方法。使用数组很容易防止外壳注入攻击,防止不必要的扩展,防止有空格时单词被破坏。唯一的缺点是数组并非在每个 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'" 被拆分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-12
      • 2012-06-29
      • 2012-02-18
      • 1970-01-01
      • 2020-04-21
      • 2019-03-19
      相关资源
      最近更新 更多