stderrをstdoutにリダイレクトしてスクリプトのファイルにリダイレクトする

stderrをstdoutにリダイレクトしてスクリプトのファイルにリダイレクトする

プロトタイプを作成する必要があるいくつかのアルゴリズムがあります。

だからプロトタイプとスクリプトを作成しました。呼び出されるスクリプトはtime.sh次のとおりです。

echo "Timing algorithm1:"
time algo1 >dev/null

echo "Timing algorithm2:"
time algo2 >dev/null

echo "Timing algorithm3:"
time algo3 >dev/null

...

さて、単純化のために...lsに置き換えてくださいalgo1。 (すべてのアルゴリズムのコードを公開し、人々にそれらをコンパイルするよう強制したくありません...)

echo " Timing ls"
time ls 2>&1 > /dev/null

呼ぶtime_ls.sh

それから私は

sh time_ls.sh > ls_sh.meas

私が何をしても、スクリプトやコマンドラインにどのリダイレクトを入力しても、2つの結果のいずれかを取得します。ターミナルから「Timing ls」というエコー出力を取得するか、ls_sh.meas反対のタイミングデータを取得します。

これは、stdoutとstderrが一緒に集まり、赤ちゃんのデータファイルを生成したくないようです。

誰でもこの奇妙な動作を説明し、回避策を提案できますか?

PS:これはbashで行われます。

ベストアンサー1

Kornのようなシェルには、以下をtime紹介するキーワードがあります。

time <pipeline>

構造。timeパイプの時はパイプで連結された命令である。

time for i in 1 2; do
       echo "$i"
     done 2>&1 | {
       read a
       read b
       ls /etc /x
     } 2> /dev/null
time ls 2>&1

タイムアウトパイプラインの例ですtime

timeパイプラインのプロセスが返された後、統計はシェルのstderrに報告されますが、パイプラインの各タイミング部分の間に統計出力を2> ...リダイレクトしません。time

リダイレクトするにはstderrが必要です。今後構成をtime ...評価します。たとえば、

{ time <pipeline>; } 2> ...
eval 'time <pipeline>' 2> ...
exec 2> ...; time <pipeline>

time問題のコマンドエラーではなく出力のみをリダイレクトするには、古い<pipeline>標準エラーを別の標準エラーに保存fdし、クロック中のパイプから復元できます。たとえば、

{
  time {
    <pipeline>
  } 2>&3 3>&-
} 3>&2 2> ...

この出力を別のコマンドにパイプします。

{
  {
    time {
      <pipeline>
    } 2>&3 3>&-
  } 3>&2 2>&1 >&4 4>&- | another command 4>&-
} 4>&-

fd 4に保存した後、標準出力も復元する必要があります。

すべてのstdout、stderr、およびtime統計をコマンドに渡すには、次のようにします。

{ time <pipeline>; } 2>&1 | a command

おすすめ記事