web-dev-qa-db-ja.com

複数のコマンドで時間を実行し、時間出力をファイルに書き込む方法は?

timeコマンドを実行して、いくつかのコマンドの時間を測定したいと思います。

私がしたいのは:

  • 合計されたすべての実行時間を測定する
  • time出力をファイルに書き込む
  • 測定中のコマンドのSTDERRSTDERRに書き込みます

私がすること[〜#〜]ない[〜#〜]やりたいことは

  • いくつかのコマンドを別のスクリプトに書き込みます(なぜこれがすべて、プログラムで生成して、[〜#〜] another [〜#〜]一時的なスクリプトは私が望んでいるよりも混乱するでしょう)

私がこれまでに試したこと:

_/usr/bin/time --output=outtime -p echo "a"; echo "b";_

動作しません。timeは最初のものでのみ実行されます。

/usr/bin/time --output=outtime -p ( echo "a"; echo "b"; )

機能しません。_(_は予期しないトークンです。

_/usr/bin/time --output=outtime -p { echo "a"; echo "b"; }_

動作しない、「そのようなファイルまたはディレクトリはありません」。

_/usr/bin/time --output=outtime -p ' echo "a"; echo "b";'_

動作しない、「そのようなファイルまたはディレクトリはありません」。

time ( echo "a"; echo "b"; ) 2>outtime

すべてのSTDERRouttimeにリダイレクトするため、機能しません。そこにはtimeの出力のみが必要です。

そしてもちろん、

_time --output=outime echo "a";_

_--output=outime: command not found_以降は機能しません。

どうすればできますか?

69
Karel Bílek

使用する sh -c 'commands'コマンドとして。例:

/usr/bin/time --output=outtime -p sh -c 'echo "a"; echo "b"'
94
Jim Paris

正解ではありませんが、質問に非常に関連しています。
複数のプログラムのタイミング統計を取得するには、括弧を組み合わせる必要があります。コマンドはセミコロンで区切ります。

time ( command1 ; command2 )
10
Martin T.

これを試して:

% (time ( { echas z; echo 2 } 2>&3 ) ) 3>&2 2>timeoutput
zsh: command not found: echas
2
% cat timeoutput                                
( { echas z; echo 2; } 2>&3; )  0.00s user 0.00s system 0% cpu 0.004 total

説明:

まず、timeの出力をリダイレクトする方法を見つける必要があります。 timeはシェルに組み込まれているため、リダイレクトを含む完全なコマンドラインを測定対象のコマンドとして使用します。したがって、

% time whatever 2>timeoutput
whatever 2> timeoutput  0.00s user 0.00s system 0% cpu 0.018 total
% cat timeoutput 
zsh: command not found: whatever

[注:janosのコメントは、これがbashには当てはまらないことを示唆しています。]サブシェルでtimeを実行してから、出力をリダイレクトすることにより、timeの出力のリダイレクトを実現できますそのサブシェル。

% (time whatever) 2> timeoutput
% cat timeoutput 
zsh: command not found: whatever
whatever  0.00s user 0.00s system 0% cpu 0.018 total

これでtimeの出力を正常にリダイレクトしましたが、その出力は測定しているコマンドのエラー出力と混合されています。 2つを分離するために、追加のファイル記述子を使用します。

「外」には

% (time ... ) 3>&2 2>timeout

つまり、ファイル記述子3に書き込まれたものはすべて、ファイル記述子2(標準エラー)が現在出力している場所(ターミナル)と同じ場所に出力されます。次に、標準エラーをファイルtimeoutにリダイレクトします。

これで、stdoutとfd 3に書き込まれたものはすべてターミナルに行き、stderrに書かれたものはすべてファイルに行きます。残りは、測定されたコマンドのstderrをfd 3にリダイレクトすることです。

% (time whatever 2>&3) 3>&2 2>timeout

ここで、複数のコマンドを時間測定するために、それらを(other!)サブシェル(括弧内)で実行する必要があります。そして、それらすべてのエラー出力をfd 3にリダイレクトするには、それらを中括弧内にグループ化する必要があります。

それで、最後に、私たちは次の場所に到着します:

% (time ( { whatever; ls } 2>&3 ) ) 3>&2 2>timeoutput

それでおしまい。

9
angus