私は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'")
時間は標準出力に出力されますが、respondの値は空です。
「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)
リダイレクトの順序を(2>&1 >/dev/null
に)入れ替えてみてください。あなたの現在のコードは、stdoutとstderrの両方を/ dev/nullに送信しています(そのため、なぜanythingが出力されるのか、ちょっと気になります)。
なぜこれが必要なのですか?構文2>&1
は、「stdr(記述子2)としてstdout(記述子1)を複製する」を意味します。実際には、stderrは現在のstdoutのコピーになります。最初に>/dev/null
を指定すると、stdoutは最初に/ dev/nullにリダイレクトされ、次にstderrが現在のstdout、つまり/ dev/nullを指します。
ただし、>/dev/null
を2番目に指定すると、stderrはリダイレクトされる前に、まず現在のstdout(通常の出力ストリーム)のコピーになります。そのため、コマンドのstderrはtty(またはインタープリター)にstdoutから出力されたかのように出力しますが、stdoutは無音です。これはあなたが望む行動です。
man bash
から:
リダイレクトの順序は重要であることに注意してください。たとえば、次のコマンド
ls > dirlist 2>&1
標準出力と標準エラーの両方をファイルdirlistに送信し、コマンド
ls 2>&1 > dirlist
標準出力がdirlistにリダイレクトされる前に標準エラーが標準出力として複製されたため、標準出力のみをファイルdirlistに送信します。