在 bash 脚本中将 SSH 输出捕获为变量
Posted
技术标签:
【中文标题】在 bash 脚本中将 SSH 输出捕获为变量【英文标题】:Capturing SSH output as variable in bash script 【发布时间】:2012-08-16 10:43:48 【问题描述】:在编写 bash 脚本时,我一直在努力解决这个问题。
基本上,我想测量远程服务器上程序的时间,所以我使用命令:
/usr/bin/time -f %e sh -c "my command > /dev/null 2>&1"
执行程序。
但是,似乎我根本无法将命令 (SSH) 的输出捕获到变量中。事实上,结果(时间)不断被打印到标准输出。
完整代码为:
respond=$(ssh $fromNode /usr/bin/time "-f" "%e" "'sh' '-c' 'virsh migrate --live $VM qemu+ssh://$toNode/system --verbose > /dev/null 2>&1'")
response 的值只是空的,虽然时间被打印到标准输出。
【问题讨论】:
superuser.com/questions/130443/… 如果你想将一个mysql查询的结果捕获到一个数组中,你可以这样做:***.com/a/57061108/470749 【参考方案1】:"time" 命令将结果打印到标准错误,而不是标准输出。因此它不会通过管道传输到您的变量中。
您应该将 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)
【讨论】:
太棒了。完全按照我的意愿工作。非常感谢您的大力帮助!顺便说一句,我只是简单地将 &> /dev/null 用于 virsh 迁移部分,因为我打算无论如何都丢弃输出【参考方案2】:尝试交换重定向的顺序(到2>&1 >/dev/null
)。您当前的代码将 stdout 和 stderr 都发送到 /dev/null (所以我有点好奇为什么会打印 anything)。
为什么这是必要的?语法2>&1
表示“将标准输出(描述符 1)复制为标准错误(描述符 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
将标准输出和标准错误都指向文件目录列表,而命令
ls 2>&1 > dirlist
仅将标准输出定向到文件 dirlist,因为标准错误被重复 在标准输出被重定向到目录列表之前作为标准输出。
【讨论】:
这些重定向只影响“virsh”命令(使其静音),而不影响“time”命令的输出。 虽然我也很好奇,为什么带有'verbose'标志的命令输出应该被静音:) 啊,你是对的。我误读了命令。看来我的报价匹配技巧需要改进:) 顺便说一句,很好的解释 - 我一直想知道这种行为,你的回答解释了事情。 详细选项是强制 virsh migrate 命令保持进程前台。它不是真的需要,但以防万一某些 virsh 版本可能会将进程发送到后台。以上是关于在 bash 脚本中将 SSH 输出捕获为变量的主要内容,如果未能解决你的问题,请参考以下文章