魔法の命令を見つけました。ここ
./my.sh 3>all 1> >(tee out >&3) 2> >(tee err >&3)
私が混乱している場所があります。
3>all
fileにファイル記述子3を設定することを意味しますかall
?- 何をすべき
1> >
ですか2> >
?私の理解によると、コマンドはでなければなりませ./my.sh 3>all 1>(tee out >&3) 2>(tee err >&3)
んが、うまくいきません。 (tee err >&3)
ファイルを上書きしないのはなぜですかall
?
これは私のものです。my.sh
#!/bin/bash
echo myecho
ls dflj
答え1
Bashのマニュアルページでこの構文を読むことができます。プロセスの置き換え:
>(list)
。プロセスリスト実行されると、その出力は/ dev / fdのファイルにリンクされます。ファイル名は、拡張結果として現在のコマンドに引数として渡されます。
このコマンドの出力を見ると、リダイレクトは行われません。
echo >(echo hi >/tmp/a) >(echo lo >/tmp/b)
それは(私のシステムで):
/dev/fd/63 /dev/fd/62
したがって、and1> >(...)
で読む必要があります。 2番目の部分はで置き換えられ、次にstdoutをファイル記述子63にリダイレクトします。 1>
>(...)
/dev/fd/63
1> /dev/fd/63
bashは別のプロセスでコマンドを実行し、>(...)
そのプロセスの標準入力をファイル記述子63に接続します。次の例を確認してください。
set -x
echo hello > >(cat -n)
Echoの標準出力は入力として接続され、次のようになりcat -n
ます。
+ echo hello
++ cat -n
1 hello
おそらくあなたが逃しているのはファイル記述子(fd)がファイルの場合クロスプロセス(bashが使用するプロセス>(...)
)を使用すると、新しいプロセスから同じfdを継承できます。したがって、これら2つのプロセスは同じfdを共有します。それにちょうど一つあります。ファイルオフセットfdの場合、プロセス1がfdに3文字を書き込むと、オフセットは0から3に移動します。プロセス2がfdに5文字を書き込むと、データはオフセット3に配置され、オフセットは8になります。プロセス2 1が別の文字を書き込むと、オフセット8に配置されます。これは、あなたの質問のtee
2つのコマンドがall
互いに上書きせずに同じファイルに書き込む方法です。
を使用すると、>&3
新しいfdは生成されません。単に現在のstdout fd 1を閉じてから、fd 3の番号をfd 1に戻します。したがって、各プロセスに異なる数字が表示されていても(man dup2
基本システムコールを参照)、両方のプロセスに対してまだ1つのfdしかありません。
答え2
meuhの優れた理論的答えよりも文字通り説明しようとすると、おそらく知っているように、基本的なファイル記述子がたくさんあります。
0
標準入力を意味します。1
標準出力を意味します。2
標準エラーを示します。
コマンドは次のことを行います。
3>all
ファイルを指す新しいファイル記述子を開きます。all
1> >(tee out >&3)
meuhが説明したように、stdout(1
)をteeコマンドによって開き、返されたファイル記述子にリダイレクトします。tee out >&3
入力(この場合はスクリプトの標準出力)をoutという名前のファイルにリダイレクトし、3
ファイル記述子が指す場所(この場合はすべてファイル)
2> >(tee err >&3)
meuhが説明したように、stderr(2
)をteeコマンドによって開き、返されたファイル記述子にリダイレクトします。tee err >&3
入力(この場合はスクリプトのstderr)をerrというファイルにリダイレクトし、3
ファイル記述子が指す場所(この場合はファイルall)
>>
あなたの意見を見ると、混乱しているのは、出力をファイルに追加したい場合は、リダイレクト演算子を使用する必要があることです。
ここではそうではありません。実際に行うことは、stdoutとstderrをファイルallを指すファイル記述子にリンクすることだけです。
効果は次のとおりです。
./my.sh > all 2>&1
まず、stdoutをallファイルにリダイレクトし、次にstderrをstdoutが指す場所にリダイレクトします。