在编写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'")
响应的值只是空的,但时间打印到标准输出。
答案 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之前作为标准输出。