
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 stderr
mü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 ttymon
oder, auf älteren Systemen, getty
ganz 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/tty
Gerä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/tty
POSIX 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>&3
oder ä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-Loadingredirfd
Tool, 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
stderr
ist zum Schreiben gedacht, nicht zum Lesen. Manchmal ist es ein dup
Likat 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 stdout
zu einer Datei weiter, und stderr
zu ./myprograms
's stdin
.
command 2>&1 >a_file | ./myprogram
Antwort3
Mit Shells wie bash
und 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 stderr
auf 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.