23

私は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'")

応答の値は空ですが、時間は標準出力に出力されます。

4

2 に答える 2

44

「time」コマンドは、結果をstdoutではなくstderrに出力します。したがって、変数にはパイプされません。

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)
于 2012-08-21T05:39:16.533 に答える
2

リダイレクトの順序を(to 2>&1 >/dev/null)に入れ替えてみてください。現在のコードは、stdoutとstderrの両方を/ dev / nullに送信しています(したがって、なぜ何かが出力されるのかについては、ちょっと興味があります)。

なぜこれが必要なのですか?構文2>&1は、「stdout(記述子1)をstderr(記述子2)として複製する」ことを意味します。実際には、stderrは現在のstdoutのコピーになります。最初に配置する>/dev/nullと、stdoutは最初に/ dev / nullにリダイレクトされ、次にstderrは現在のstdout、つまり/ dev/nullを指します。

ただし、>/dev/null2番目に配置すると、stdoutがリダイレクトされる前に、stderrが最初に現在のstdout(通常の出力ストリーム)のコピーになります。したがって、コマンドのstderrは、stdoutが無音になっている間、それがstdoutからのものであるかのようにtty(またはインタープリター)に出力します。これはあなたが望む振る舞いです。

差出人man bash

リダイレクトの順序が重要であることに注意してください。たとえば、コマンド

ls > dirlist 2>&1

コマンドがコマンドを実行している間、標準出力と標準エラーの両方をファイルdirlistに送信します。

ls 2>&1 > dirlist

標準出力がdirlistにリダイレクトされる前に、標準エラーが標準出力として複製されたため、標準出力のみをファイルdirlistに転送します。

于 2012-08-21T05:37:45.680 に答える