Dateideskriptor 2 ist zum Lesen und Schreiben geöffnet

Dateideskriptor 2 ist zum Lesen und Schreiben geöffnet

Dies ist mein C-Programm, das ich von stderr lese und schreibe

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

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

Meine Frage: Wie kann ich einen stderr dorthin senden? Die meisten Suchvorgänge zeigen Folgendes an: in der Bash-Umleitung

command 2> file

Dies sendet den Standardfehler jedoch an eine Datei.

Wie kann ich an mein Programm weitergeben. Wie pip,

command 2 "somthing here" ./myprogram

Danke für die Antworten.

Antwort1

Es überrascht viele Leute, dass in den meisten Nachschlagewerken und Dokumentationen immer der Standardfehler als Ausgabewert angegeben wird.bereits zum Lesen und Schreiben geöffnetIhr Programm sehrdürfenaus Dateideskriptor 2 lesen.

(Hinweis: In dieser Antwort verwende ich die tatsächlichen Dateideskriptornummern. DieC-Streamswie stderrmüssen nicht unbedingt mit diesen Dateideskriptoren übereinstimmen, da ein Programm sie ändern kann, und es sorgt für zusätzliche Verwirrung, wenn man darüber spricht, was die C-Streams tun. Ihr Programm verwendet read().)

Dateideskriptor 2 ist zum Lesen und Schreiben geöffnet

Für Programme in Anmeldesitzungen, bei denen in einem übergeordneten Prozess keine Umleitung verwendet wurde, ist Dateideskriptor 2 (Standardfehler) normalerweise ein Duplikat von Dateideskriptor 0 (Standardeingabe). Beide verweisen auf denselben zugrunde liegendenDateibeschreibung, normalerweise das Terminal der Anmeldesitzung (geöffnet und dupliziert von ttymonoder, auf älteren Systemen, gettyganz zu Beginn der Sitzung).

Wenn Sie aus Dateideskriptor 2 lesen, erhalten Sie die gleiche Eingabe, als hätten Sie aus Dateideskriptor 0 gelesen.

Übrigens: Das Lesen aus dem Dateideskriptor 2 wurde häufig für Dinge wie die Passworteingabe durchgeführt; bevor das /dev/ttyGerät eingeführt wurde, etwa 1977. Der Grund für das Lesen aus dem Dateideskriptor 2 bestand darin, Eingaben vom ursprünglichen Terminal zu erhalten, wenn der Dateideskriptor 0 woanders hin umgeleitet worden war (wie es beispielsweise in der Mitte einer Pipeline der Fall ist).

Obwohl /dev/ttyPOSIX bereits seit über 40 Jahren verfügbar ist, muss der Dateideskriptor 2 auch zum Lesen geöffnet sein.

Was Ihr Programm nicht tut

Das Lesen der Ausgabe des Dateideskriptors 2 eines anderen Programms ist eine andere Sache. Das kann man nicht einfach tunvon selbst, ohne die Standardausgabe mit der Standardfehlerausgabe zu verschmelzen. Normalerweise handelt es sich dabei um eine Reihe von 3>&1 1>&2 2>&3oder ähnliche Vertauschungen. Einige Shells erlauben Pipes auf dem Ausgabedateideskriptor 2 durch den Aufruf

prog1 2| prog2

Aber solche Granaten sind selten, und das ist nicht das, wasdeinProgrammbedarf auf jeden Fall.

Senden von Eingaben an Ihr Programm

Wenn Sie möchten, dass Ihr Programm, das aus dem Dateideskriptor 2 liest, von etwas liestandereals vom Terminal aus, leiten Sie diesen Dateideskriptor natürlich um. Siekönnteverwenden Sie die normaleEingangUmleitungssyntax (der <Operator in der Shell), aber Bibliotheken in Ihrem Programm oder sogar anderer Code, den Sie anderswo geschrieben haben, gehen davon aus, dass sie in diesen Dateideskriptor schreiben können.

Die Shell ermöglicht Ihnen die Verwendung des <>Umleitungsoperators, der eine Datei explizit zum Lesen und Schreiben öffnet. Dies verwenden Sie, wenn Sie den Dateideskriptor 2 Ihres Programms umleiten.

./myprogram 2<>filename

Außer der Shell-Umleitung gibt es viele Tools, die die Manipulation von Dateideskriptoren ermöglichen. Zum Beispiel: Mit Laurent Bercots Chain-LoadingredirfdTool, das mit Execline geliefert wird, ähnelt diese Umleitung eher Ihrer Hypothese:

redirfd -u 2 filename ./myprogram

Es gibt auch Shell-Syntax in Shells wie Bourne Again und Z (aber nicht in den Almquist-Shells), um "hier Dokumente" und "hier Zeichenfolgen" für Dateideskriptor 2 bereitzustellen. Beachten Sie, dass Dateideskriptor 2 geöffnet wirdschreibgeschütztdurch diese Granaten in diesem Fall.

./myprogram 2<<< "here string"

Antwort2

stderrist zum Schreiben gedacht, nicht zum Lesen. Manchmal ist es ein dupLikat von stdin(z. B. wenn alle 3 Ein-/Ausgänge/Fehler mit dem Terminal verbunden sind). Um die Standardfehlerausgabe eines anderen Programms zu lesen, leiten Sie die Standardfehlerausgabe dieses Programms auf die Standardeingabe eines anderen Programms um.

zB leitet zu stdoutzu einer Datei weiter, und stderrzu ./myprograms's stdin.

command 2>&1 >a_file | ./myprogram

Antwort3

Mit Shells wie bashund zsh(aber nicht einfachem POSIX sh) können Sie die Standardfehlerausgabe eines Programms über auf die Standardeingabe eines anderen Programms umleiten firstprogram 2> >(second program).

Beispiel:

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

Antwort4

Damit die Shell eine Eingabeumleitung für einrichtet stderr, verwenden Sie <, <<oder <<<und stellen die Dateideskriptornummer voran:

./myprog 2< somefile.txt

oder

./myprog 2<<< "some text"

Wenn Sie jedoch stderrauf diese Weise umleiten, kann das Programm nichtAusgabeDies bedeutet, dass Sie keine Fehlermeldungen sehen, die das Programm (oder die von ihm verwendeten Bibliotheken) möglicherweise auszugeben versucht. Darüber hinaus erhält das Programm Fehlermeldungen, wenn es versucht, diese Nachrichten zu schreiben.

Sie sollten vielleicht noch einmal darüber nachdenken, ob es eine andere Möglichkeit gibt, das zu tun, was Sie tun. Ziehen Sie zumindest in Erwägung, z. B. fd 3 zu verwenden, wenn die Idee darin besteht, dem Programm Eingaben bereitzustellen.

verwandte Informationen