捕获 SSH 输出作为 bash 脚本中的变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12048906/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Capturing SSH output as variable in bash script
提问by Andy Dang
I've been struggling with this problem when writing a bash script.
Basically, I want to measure the time of a program on a remote server, so I use the command:
/usr/bin/time -f %e sh -c "my command > /dev/null 2>&1"
to execute the program.
However, it appears that I cannot capture the output of my command (SSH) to a variable at all. In fact, the result (time) keeps getting printed out to stdout.
在编写 bash 脚本时,我一直在努力解决这个问题。基本上,我想测量一个程序在远程服务器上的时间,所以我使用命令:
/usr/bin/time -f %e sh -c "my command > /dev/null 2>&1"
来执行程序。但是,似乎我根本无法将命令 (SSH) 的输出捕获到变量中。事实上,结果(时间)不断被打印到标准输出。
The full code is:
完整代码是:
respond=$(ssh ${fromNode} /usr/bin/time "-f" "%e" "'sh' '-c' 'virsh migrate --live ${VM} qemu+ssh://${toNode}/system --verbose > /dev/null 2>&1'")
The value of respond is just empty, though the time is printed out to the standard output.
虽然时间被打印到标准输出,但响应的值只是空的。
回答by Rogach
"time" command prints result to stderr, not to stdout. Thus it is not piped into your variable.
“time”命令将结果打印到 stderr,而不是 stdout。因此它不会通过管道传输到您的变量中。
You should reroute stderr to stdout to achieve what you want:
您应该将 stderr 重新路由到 stdout 以实现您想要的:
result=$(ssh host time "command" 2>&1)
And your full code can look something like this:
您的完整代码可能如下所示:
respond=$(ssh ${fromNode} /usr/bin/time "-f" "%e" "'sh' '-c' 'virsh migrate --live ${VM} qemu+ssh://${toNode}/system > /dev/null 2>&1'" 2>&1)
回答by nneonneo
Try swapping the order of your redirections around (to 2>&1 >/dev/null
). Your current code is sending both stdout and stderr to /dev/null (so I'm kind of curious as to why anythingis printed at all).
尝试在 (to 2>&1 >/dev/null
)周围交换重定向的顺序。您当前的代码将 stdout 和 stderr 都发送到 /dev/null (所以我很好奇为什么要打印任何内容)。
Why is this necessary? The syntax 2>&1
means 'duplicate stdout (descriptor 1) as stderr (descriptor 2)'; in effect, stderr is made into a copy of the current stdout. If you put >/dev/null
first, then stdout is first redirected to /dev/null, and then stderr is pointed at the current stdout, i.e. /dev/null.
为什么这是必要的?语法2>&1
表示“将标准输出(描述符 1)复制为标准错误(描述符 2)”;实际上,stderr 被制作成当前 stdout 的副本。如果>/dev/null
先放,那么stdout首先被重定向到/dev/null,然后stderr指向当前的stdout,即/dev/null。
But if you put >/dev/null
second, stderr will first become a copy of the current stdout (the normal output stream), before stdout is redirected. So the command's stderr prints to the tty (or the interpreter) as if it came from stdout, while stdout is silenced. This is the behaviour you want.
但是如果你把它放在>/dev/null
第二个,stderr 将首先成为当前 stdout(正常输出流)的副本,然后 stdout 被重定向。所以命令的 stderr 打印到 tty(或解释器),就好像它来自 stdout 一样,而 stdout 被静音。这是您想要的行为。
From man bash
:
来自man bash
:
Note that the order of redirections is significant. For example, the command
ls > dirlist 2>&1
directs both standard output and standard error to the file dirlist, while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the standard error was duplicated as standard output before the standard output was redirected to dirlist.
请注意,重定向的顺序很重要。例如,命令
ls > dirlist 2>&1
将标准输出和标准错误都指向文件 dirlist,而命令
ls 2>&1 > dirlist
仅将标准输出定向到文件 dirlist,因为在将标准输出重定向到 dirlist 之前,标准错误已复制为标准输出。