Wie werden Programme an eine andere Stelle als STDOUT / STDERR ausgegeben? Wie vermeide ich es?

15

Anscheinend kenne ich nicht alle verfügbaren Ausgabeziele. Ich weiß über stdout( &1) und stderr( &2) Bescheid . Nachdem ich jedoch beide Deskriptoren umgeleitet habe, erhalte ich manchmal immer noch eine Ausgabe in meiner Konsole!

Das einfachste Beispiel, an das ich denken kann, ist GNU Parallel. Jedes Mal, wenn ich es benutze, sehe ich einen Zitierhinweis. Selbst wenn ich das tue &2>1 > file, sehe ich immer noch den Hinweis.

Und das gilt auch für emerge: Wenn ich emerge laufen lasse und es Probleme gibt, werden einige Informationen weder gedruckt stdoutnoch weitergeleitet stdin, da ich sie umleite und sie immer noch durchkommen.

Ich löse diese Probleme meistens mit script, frage mich aber immer noch, was das Problem verursacht.

MatthewRock
quelle
1
Bitte geben Sie ein vollständiges Beispiel an.
Kusalananda
welche schale? Schauen Sie sich mywiki.wooledge.org/BashFAQ/055 und stackoverflow.com/questions/876239/…
Sundeep,
8
Sie werden sie nicht alle bekommen . Ein Skript kann immer schreiben /dev/tty.
Satō Katsura
1
Wie für GNU parallel: mkdir ~/.parallel; touch ~/.parallel/will-citeDeaktiviert die nervige Nachricht. Alternativ können Sie sich nach anderen Implementierungen von umsehen parallel.
Satō Katsura
2
@OleTange Weil es kein Problem ist - ich frage, warum etwas passiert und ich verwende es parallelals Beispiel.
MatthewRock

Antworten:

40

Die von Ihnen verwendete Syntax ist falsch.

cmd &2>1 >file

wird aufgeteilt als

cmd &
2>1 >file

Dieser Wille:

  1. Führen Sie cmdals Hintergrundjob ohne Umleitungen
  2. In einem separaten Prozess (ohne Befehl!) Wird stderrzu einer Datei umgeleitet , die buchstäblich aufgerufen wird, 1und stdoutzufile

Die gewünschte Syntax lautet:

cmd >file 2>&1

Die Reihenfolge der Operationen ist wichtig. Dieser Wille:

  1. Weiterleiten stdoutanfile
  2. Weiterleiten stderran &1- dh dasselbe Dateihandle wiestdout

Das Ergebnis ist, dass beide stderrund stdoutweitergeleitet werden file.

In bash, eine einfacheren Nicht-Standard (und so ich werde es nicht empfehlen, auf Portabilität Gründen) Syntax cmd &> filemacht das Gleiche.

Stephen Harris
quelle
Nett, danke. Das andere Problem könnte sein /dev/tty, aber hoffentlich passiert dies nicht zu oft (wenn überhaupt).
MatthewRock
5
Wenn Sie den atBefehl auf Ihrem Computer haben und über die Berechtigung verfügen, ihn zu verwenden, können Sie den Befehl über ausführen at now. Einzelheiten finden Sie auf der Manpage. Dadurch wird der Befehl über einen Batch-Prozessmechanismus ausgeführt, und der Prozess hat niemals ein tty, in das geschrieben werden kann. Aber im Allgemeinen würde ich mir keine Sorgen um diesen Randfall machen. Normalerweise werden nur Prozesse verwendet, die eine Interaktion erfordern und die den Benutzern trotz Umleitung absichtlich angezeigt werden müssen /dev/tty.
Stephen Harris
war dort, habe das gemacht
davidbak
10

Es gibt zwei Probleme.

Der erste ist, dass die Reihenfolge wichtig ist, der zweite ist /dev/tty.

Verwenden wir dieses Skript als Beispielskript, von dem wir die Ausgabe erfassen möchten:

test.sh:

#!/bin/bash

echo dada
echo edada 1>&2
echo ttdada >/dev/tty

Nun sehen wir uns die Ausgaben der Befehle an:

./testmyscript.sh 2>&1 >/dev/null:

edada
ttdada

Da die Auswertungsreihenfolge von links nach rechts ist, erhalten wir zuerst "Weiterleiten stderran den Ort stdout, an dem ausgegeben wird (also Konsolenausgabe)". Dann werden wir "umgeleitet stdoutzu" /dev/null. Am Ende ergibt sich folgende Situation:

stdout-> /dev/null stderr-> Konsole

Also machen wir es richtig:

./testmyscript.sh >/dev/null 2>&1

Und wir bekommen:

ttdada.

Jetzt führen wir "Weiterleiten stdoutan /dev/null" und dann "Weiterleiten stderr an wo stdout zeigt" (so, /dev/null) aus. Hurra!

Wir haben jedoch immer noch ein Problem. Programm druckt auf /dev/tty. Jetzt weiß ich nicht, wie ich diese Art von Verhalten korrigieren soll, also wirst du es höchstwahrscheinlich brauchen script, aber hoffentlich kommt dieses Verhalten nicht allzu oft vor.

MatthewRock
quelle