在bash脚本中将SSH输出捕获为变量

时间:2012-08-21 05:29:20

标签: bash ssh stdout

在编写bash脚本时,我一直在努力解决这个问题。 基本上,我想测量远程服务器上程序的时间,所以我使用命令: /usr/bin/time -f %e sh -c "my command > /dev/null 2>&1"执行程序。 但是,似乎我无法将命令(SSH)的输出捕获到变量。事实上,结果(时间)一直打印到stdout。

完整的代码是:

respond=$(ssh ${fromNode} /usr/bin/time "-f" "%e" "'sh' '-c' 'virsh migrate --live ${VM} qemu+ssh://${toNode}/system --verbose > /dev/null 2>&1'")

响应的值只是空的,但时间打印到标准输出。

2 个答案:

答案 0 :(得分:29)

“time”命令将结果打印到stderr,而不是stdout。因此,它不会通过管道传输到您的变量中。

您应该将stderr重新路由到stdout以实现您想要的目标:

 result=$(ssh host time "command" 2>&1)

您的完整代码可能如下所示:

 respond=$(ssh ${fromNode} /usr/bin/time "-f" "%e" "'sh' '-c' 'virsh migrate --live ${VM} qemu+ssh://${toNode}/system > /dev/null 2>&1'" 2>&1)

答案 1 :(得分:2)

尝试交换重定向的顺序(到2>&1 >/dev/null)。你当前的代码是将stdout和stderr发送到/ dev / null(所以我很好奇为什么打印任何)。

为什么这有必要?语法2>&1表示'重复stdout(描述符1)为stderr(描述符2)';实际上,stderr被制作成当前标准输出的副本。如果先放置>/dev/null,则先将stdout重定向到/ dev / null,然后将stderr指向当前的stdout,即/ dev / null。

但是如果你把>/dev/null放在第二位,stderr将首先成为当前stdout(正常输出流)的副本,然后重定向stdout。所以命令的stderr打印到tty(或解释器)就好像它来自stdout,而stdout被静音了。这是你想要的行为。

来自man bash

  

请注意,重定向的顺序非常重要。例如,命令

ls > dirlist 2>&1
     

将标准输出和标准错误都指向文件dirlist,同时命令

ls 2>&1 > dirlist
     

仅将标准输出定向到文件dirlist,因为标准错误是重复的   在标准输出被重定向到dirlist之前作为标准输出。