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

答え2

time同じログファイルに各プロトタイプの出力と出力を含めたいと思います。

#!/bin/bash
# Name as "algon1"    (
    echo "Timing algorithm1:"
    time algo1 >/dev/null
    
    echo "Timing algorithm2:"
    time algo2 >/dev/null
    
    echo "Timing algorithm3:"
    time algo3 >/dev/null
) > algon1.log 2>&1

次に、ファイルを実行可能にして呼び出します。

chmod a+x algon1
./algon1

または、出力ファイル名をスクリプトにハードコードしない場合は、代わりに出力標準出力:

#!/bin/bash
# Name as "algon2"
(
    echo "Timing algorithm1:"
    time algo1 >/dev/null
    
    echo "Timing algorithm2:"
    time algo2 >/dev/null
    
    echo "Timing algorithm3:"
    time algo3 >/dev/null
) 2>&1

そして

chmod a+x algon2
./algon2 | tee algon2.log

両方のスクリプトでアルゴリズム出力にタイミングが含まれるようにするには、各行>/dev/nullからそれらを削除できます。time

答え3

スクリプトの先頭でリダイレクトを定義します。

#!/bin/bash
exec 2>&1

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

echo Timing ls 2
time ls /jabberwocks &>/dev/null
./time_ls.sh > ls_sh.meas

関連情報