ファイル記述子2は読み取りと書き込み用に開かれています

ファイル記述子2は読み取りと書き込み用に開かれています

これは私が書いたstderrから読み取ったCプログラムです

#include <uninstd.h>
#include <stdio.h>

int main(void) {
 char buff[3];
 read(2, buff, sizeof(buff));
 printf("%s", buff");
 return 0;
}

私の質問は、stderrをどのように送信できるかということです。ほとんどの検索では、bashリダイレクトのように表示されます。

command 2> file

しかし、これは stderr をファイルに送信します。

どうすればプログラムに渡せますか。pipのように、

command 2 "somthing here" ./myprogram

回答ありがとうございます。

答え1

ほとんどの参考書やドキュメントでは標準誤差を出力として常に言及していることを考えると、実際には通常はすでに読み取り+書き込み用にオープンされていますあなたのプログラムはとてもできるファイル記述子 2 から読み取ります。

(注:この回答では実際のファイル記述子番号を使用しています。C ストリームなどはstderr、プログラムが変更できるため、実際にこれらのファイル記述子に対応する必要はなく、C ストリームの動作について説明する際に混乱が生じます。プログラムでは を使用していますread()

ファイル記述子2は読み取りと書き込み用に開かれています

親プロセスでリダイレクトが使用されていないログインセッションのプログラムの場合、ファイル記述子2(標準エラー)は通常、ファイル記述子0(標準入力)の複製です。どちらも同じ基礎を参照します。ファイル説明これは通常、ログイン セッションのターミナルです (セッションの開始時にttymon、または古いシステムではgettyセッションの開始時に開かれ、複製されます)。

ファイル記述子 2 から読み取ると、ファイル記述子 0 から読み取った場合と同じ入力が得られます。

ところで、ファイル記述子 2 からの読み取りは、デバイスが導入される前の 1977 年頃には、パスワード入力などの目的で頻繁に行われていました。/dev/ttyファイル記述子 2 からの読み取りを行う理由は、ファイル記述子 0 が他の場所にリダイレクトされた場合 (たとえば、パイプラインの途中の場合など) に、元の端末から入力を取得するためでした。

/dev/ttyPOSIX は 40 年以上も前から利用可能になっていますが、それでもファイル記述子 2 を読み取り用に開く必要があります。

プログラムが行っていないこと

別のプログラムのファイル記述子2の出力を読み取ることは別のことです。簡単にはできません。それ自体で、標準出力と標準エラーをマージせずに出力します。通常は、一連の3>&1 1>&2 2>&3または同様のスワップを伴います。いくつかのシェルでは、出力ファイル記述子2にパイプを許可しています。

prog1 2| prog2

しかし、そのような貝は稀であり、それがあなたのいずれにせよプログラムが必要です。

プログラムに入力を送信する

ファイル記述子2から何かを読み出すプログラムを作りたい場合他の端末からではなく、もちろんそのファイル記述子をリダイレクトします。できた通常の使用入力リダイレクト構文 (<シェルの演算子) ですが、プログラム内のライブラリ、または他の場所で記述した他のコードでも、このファイル記述子に書き込むことができると想定されます。

シェルでは、読み取りと書き込みの両方でファイルを明示的に開くリダイレ​​クト演算子を使用できます<>。これは、プログラムのファイル記述子 2 をリダイレクトするときに使用します。

./myprogram 2<>filename

シェルのリダイレクト以外にも、ファイル記述子の操作を可能にするツールはたくさんあります。例えば、Laurent Bercotのチェーンロードredirfdexecline に付属するツールでは、このリダイレクトはあなたの仮説に似ているように見えます:

redirfd -u 2 filename ./myprogram

Bourne AgainやZシェル(Almquistシェルではない)のようなシェル構文では、ファイル記述子2に「ヒアドキュメント」と「ヒア文字列」を提供する。ファイル記述子2は次のように開かれる。読み取り専用この場合はこれらのシェルによって。

./myprogram 2<<< "here string"

答え2

stderrは、読み取り用ではなく書き込み用です。 場合によっては、(たとえば、3 つの in/out/err すべてが端末に接続されている場合など)dupの複製になりstdinます。 別のプログラムの stderr を読み取るには、そのプログラムの stderr を別のプログラムの stdin にリダイレクトします。

たとえば、 to はstdoutファイルへ、stderrto./myprogramsは へ転送しますstdin

command 2>&1 >a_file | ./myprogram

答え3

bashやのようなシェルzsh(ただし、単純な POSIX ではないsh) を使用すると、 を介して、あるプログラムの標準エラーを別のプログラムの標準入力にリダイレクトできますfirstprogram 2> >(second program)

例:

$ perl -E 'say "perl stdout"; warn "perl stderr\n"' 2> >(awk '{print "awk", $0}')
perl stdout
awk perl stderr

答え4

シェルに の入力リダイレクトを設定させるには、 、または をstderr使用し、ファイル記述子番号の前に を付けます。<<<<<<

./myprog 2< somefile.txt

または

./myprog 2<<< "some text"

しかし、このようにリダイレクトするとstderr、プログラムは出力つまり、プログラム (またはプログラムが使用するライブラリ) が出力しようとするエラー メッセージは表示されず、さらに、プログラムはそれらのメッセージを書き込もうとするとエラーを受け取ります。

何をするにしても、別の方法があるかどうかを再検討したほうがよいかもしれません。少なくとも、プログラムに何らかの入力を提供する場合は、たとえば fd 3 の使用を検討してください。

関連情報