Ich habe das folgende Programm in new.c gespeichert
int main()
{
a;
return 0;
}
Es wird eine Fehlermeldung zurückgegeben. Ich möchte diese Nachricht an eine Datei senden. Also habe ich den folgenden Befehl verwendet
gcc new.c > temp.txt
Trotzdem bekam ich die Ausgabe auf dem Terminal. Ich benutze Ubuntu 13.04. Wie kann ich es zum Laufen bringen?
Antworten:
Wenn Sie ein Programm mit kompilieren
gcc
, gibt es verschiedene Arten der Ausgabe: anstdout
undstderr
. Normalerweise>
leitet derstdout
Stream den Stream in eine Datei (z. B. wird das Ergebnis von a anprintf("hello world\n");
gesendetstdout
). Das wird jedochstderr
weiterhin an den Bildschirm gesendet, da davon ausgegangen wird, dass es sich um "etwas Außergewöhnliches handelt, über das Sie informiert werden müssen".Es gibt eine Möglichkeit, stderr in eine Datei umzuleiten - Sie tun dies mit dem folgenden (nicht sehr intuitiven) Befehl:
Wo
&>
ist "Bash Shorthand" für "Alles umleiten". Wie von @CharlesDuffy hervorgehoben wurde, ist das POSIX-kompatible FormularDies bedeutet "kompiliere 'new.c' und sende
stdout
anmyFile
. Und sendestderr
(2) an den gleichen Ort wiestdout
(&1
=" den gleichen Ort wie stdout ").Weitere Informationen zu verschiedenen Weiterleitungen finden Sie unter http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-3.html und http://mywiki.wooledge.org/BashFAQ/055
Übrigens, wenn Sie etwas aus Ihrem Programm heraus speziell an senden möchten
stderr
, können Sie dies wie folgt tunWenn Sie dies in ein Programm aufnehmen, das Programm ausführen und die "normale" Ausgabe an eine Datei senden, wird dies weiterhin auf der Konsole angezeigt. Wenn Sie also die oben in die ausführbare Datei kompilieren
urgent
, geben Sie dannAn der Konsole wird Ihre Ausgabe auf dem Bildschirm angezeigt.
quelle
>myFile 2>&1
) sowie die Bash-Erweiterung (&>
) einführen .Da
>
nur stdout umgeleitet wird und Fehler geschrieben werden,stderr
müssen Sie stattdessen eine der folgenden Methoden verwenden:...oder...
&>
ist eine BASH-Erweiterung, die sowohlstdout
als auchstderr
zu einer Datei umleitet ; Andernfalls ist es am einfachsten, zuerst stdout (>temp.txt
) umzuleiten und dann stderr (FD 2) zu einer Kopie des bereits umgeleiteten Dateihandles auf stdout (FD 1) zu machen2>&1
.quelle
Wie die anderen gesagt haben, bietet Linux zwei verschiedene Ausgabestreams:
Bei stdout oder "Standardausgabe" werden alle regulären Ausgaben ausgeführt.
Sie können mit dem Dateideskriptor darauf verweisen
1
.stderr oder "Standardfehler" ist ein separater Stream für Out-of-Band-Informationen.
Sie können mit dem Dateideskriptor darauf verweisen
2
.Warum zwei verschiedene Ausgabestreams? Betrachten Sie eine Pipeline imaginärer Befehle:
Stellen Sie sich nun vor, der
decrypt
Befehl schlägt fehl und generiert eine Fehlermeldung. Wenn es diese Nachricht anstdout
senden würde, würde es in die Pipe senden, und wenn es nicht das Wort "geheim" hätte, würden Sie es nie sehen. Sie erhalten also eine leere Ausgabedatei, ohne zu wissen, was schief gelaufen ist.Da die Pipe jedoch nur erfasst
stdout
, kann derdecrypt
Befehl seine Fehler an die Stelle sendenstderr
, an der sie auf der Konsole angezeigt werden.Sie können umleiten
stdout
undstderr
entweder zusammen oder unabhängig voneinander:Sie können die Fehler umleiten
stdout
und so verarbeiten, als wären sie normale Ausgaben:Sie können auch eine "Kurzschreibweise" verwenden, um sowohl stdout als auch stderr in dieselbe Datei umzuleiten :
Und schließlich der
>
wird Bediener zunächst gestutzt seine Ausgabedatei vor dem Schreiben. Wenn Sie stattdessen Daten an eine vorhandene Datei anhängen möchten , verwenden Sie den>>
Operator:quelle
$FOO
) ist eine häufige Fehlerquelle, und die Demonstration in Beispielen ist nicht so großartig. (2) Die Verwendung von Variablennamen in Großbuchstaben ist der Hauptgrund für Namespace-Konflikte zwischen Umgebungsvariablen und integrierten Variablen (Großbuchstaben gemäß Konvention) und lokalen Variablen (Kleinbuchstaben gemäß Konvention). (3) Das Ermutigen von Personen zur wiederholten Verwendung>>
(wodurch die Datei jedes Mal neu geöffnet wird, wenn sie in einem Befehl verwendet wird), anstatt eine Datei einmal zu öffnen und den Dateideskriptor für die Verwendung durch mehrere Befehle offen zu lassen, führt zu ineffizientem Code.exec 4>secrets; echo "this is a secret" >&4; echo "this is another secret" >&4
exec
Einfachheit halber absichtlich weggelassen , obwohl es in der Praxis im Allgemeinen eine bessere Strategie ist.command₁
>
output_file
;
command₂
>>
the_same_output_file
(
command₁
;
command₂
) >
output_file
{
command₁
;
command₂
; } >
output_file
{
;
}