Gibt es ein Standard-Bash-Tool, das als Echo fungiert, jedoch nicht in stdout, sondern in stderr ausgegeben wird?
Ich weiß, ich kann echo foo 1>&2
, aber es ist ziemlich hässlich und, ich vermute, fehleranfällig (z. B. eher fehlerhaft bearbeitet, wenn sich Dinge ändern).
Diese Frage ist alt, aber Sie könnten dies tun, was das Lesen erleichtert:
>&2 echo "error"
Der Operator >&2
bedeutet wörtlich, die Adresse des Dateideskriptors 1 (stdout
) an die Adresse des Dateideskriptors 2 (stderr
) für diesen Befehl umzuleiten1. Je nachdem, wie tief Sie es verstehen wollen, lesen Sie dies: http://wiki.bash-hackers.org/howto/redirection_tutorial
Um Interaktionen mit anderen Weiterleitungen zu vermeiden, verwenden Sie eine Subshell
(>&2 echo "error")
1>&2
kopiert den Dateideskriptor # 2 in den Dateideskriptor # 1. Nachdem diese Umleitung durchgeführt wurde, beziehen sich beide Dateideskriptoren daher auf dieselbe Datei: Der einzige Dateideskriptor # 2 war ursprünglich.
Sie können eine Funktion definieren:
echoerr() { echo "[email protected]" 1>&2; }
echoerr hello world
Dies wäre schneller als ein Skript und hat keine Abhängigkeiten.
Der Bash-spezifische Vorschlag von Camilo Martin verwendet einen "Here-String" und gibt alles aus, was Sie daran übergeben, einschließlich Argumenten (-n), die das Echo normalerweise verschlucken würde:
echoerr() { cat <<< "[email protected]" 1>&2; }
Die Lösung von Glenn Jackman vermeidet auch das Problem des Schluckproblems:
echoerr() { printf "%s\n" "$*" >&2; }
Da 1
die Standardausgabe ist, müssen Sie sie nicht explizit vor einer Ausgabeumleitung wie >
benennen, sondern können einfach Folgendes eingeben:
echo Diese Nachricht geht an stderr> & 2
Da Sie sich besorgt zu sein scheinen, dass 1>&2
Sie nur schwer zuverlässig tippen kann, könnte die Beseitigung des überflüssigen 1
eine leichte Ermutigung für Sie sein!
Andere Option
echo foo >>/dev/stderr
Nein, das ist die Standardmethode. Es sollte keine Fehler verursachen.
Dies ist eine einfache STDERR-Funktion, die die Pipe-Eingabe an STDERR umleitet.
#!/bin/bash
# *************************************************************
# This function redirect the pipe input to STDERR.
#
# @param stream
# @return string
#
function STDERR () {
cat - 1>&2
}
# remove the directory /bubu
if rm /bubu 2>/dev/null; then
echo "Bubu is gone."
else
echo "Has anyone seen Bubu?" | STDERR
fi
# run the bubu.sh and redirect you output
[email protected]:~$ ./bubu.sh >/tmp/bubu.log 2>/tmp/bubu.err
Wenn es Ihnen nichts ausmacht, die Nachricht auch in syslog zu protokollieren, ist not_so_ugly der folgende Weg:
logger -s $msg
Die Option -s bedeutet: "Ausgabe der Nachricht an Standardfehler sowie an das Systemprotokoll."
Verwenden Sie nicht cat
, da einige hier erwähnt werden. cat
ist ein Programm , während echo
und printf
bash (Shell) sind. Das Starten eines Programms oder eines anderen Skripts (auch oben erwähnt) bedeutet, dass ein neuer Prozess mit all seinen Kosten erstellt wird. Durch die Verwendung von eingebauten Funktionen sind Schreibfunktionen recht billig, da kein Prozess (-Umgebung) erstellt (ausgeführt) werden muss.
Der Benutzer fragt "Gibt es ein Standardwerkzeug zur Ausgabe ( pipe ) an stderr", lautet die kurze Antwort: NEIN ... warum? Das Rediredcting von Pipes ist ein grundlegendes Konzept in Systemen wie Unix (Linux ...) und bash (sh) baut auf diesen Konzepten auf.
Ich stimme mit dem Opener überein, dass das Umleiten mit Notizen wie diesen: &2>1
für moderne Programmierer nicht sehr angenehm ist, aber das ist bash. Bash war nicht dazu gedacht, große und robuste Programme zu schreiben, es soll den Admins dabei helfen, mit weniger Tastendruck dort zu arbeiten ;-)
Und zumindest können Sie die Weiterleitung an beliebiger Stelle in der Zeile platzieren:
$ echo This message >&2 goes to stderr
This message goes to stderr
Hinweis: Ich beantworte die post-nicht die irreführende/vage Frage "Echo, die an stderr ausgibt" (bereits von OP beantwortet).
Verwenden Sie eine Funktion, um die Intentionanzuzeigen und die gewünschte Implementierung zu erhalten. Z.B.
#!/bin/bash
[ -x error_handling ] && . error_handling
filename="foobar.txt"
config_error $filename "invalid value!"
output_xml_error "No such account"
debug_output "Skipping cache"
log_error "Timeout downloading archive"
notify_admin "Out of disk space!"
fatal "failed to open logger!"
Und error_handling
sein:
[email protected]
config_error() { filename="$1"; shift; echo "Config error in $filename: $*" 2>&1; }
output_xml_error() { echo "<error>$*</error>" 2>&1; }
debug_output() { [ "$DEBUG"=="1" ] && echo "DEBUG: $*"; }
log_error() { logger -s "$*"; }
fatal() { which logger >/dev/null && logger -s "FATAL: $*" || echo "FATAL: $*"; exit 100; }
notify_admin() { echo "$*" | mail -s "Error from script" "$ADMIN_EMAIL"; }
Gründe, die Bedenken in OP behandeln:
Andere Gründe:
Dies wurde bereits und mit vielen Stimmen beantwortet. Nur für das Protokoll:
echo "my errz" > /proc/self/fd/2
wird effektiv in stderr
ausgegeben. Erläuterung: /proc/self
ist eine Verknüpfung zum aktuellen Prozess und /proc/self/fd
enthält die geöffneten Dateideskriptoren des Prozesses. Dann stehen 0
, 1
und 2
für stdin
, stdout
und stderr
.
Ich fand es lesbarer. Auch dies kann in den meisten Linux-Distributionen funktionieren:
echo "my errz" > /dev/stderr
Es macht es deutlich lesbarer.
read
ist ein in Shell integrierter Befehl, der in stderr druckt und wie ein Echo verwendet werden kann, ohne Umleitungstricks auszuführen:
read -t 0.1 -p "This will be sent to stderr"
Der -t 0.1
ist ein Timeout, bei dem die Hauptfunktionen von read deaktiviert werden, indem eine Zeile stdin in einer Variablen gespeichert wird.
Machen Sie ein Skript
#!/bin/sh
echo $* 1>&2
das wäre dein Werkzeug.
Oder machen Sie eine Funktion, wenn Sie kein Skript in einer separaten Datei haben möchten.
Eine andere Option, auf die ich kürzlich gestoßen bin, ist folgende:
{
echo "First error line"
echo "Second error line"
echo "Third error line"
} >&2
Hierbei werden nur integrierte Bash-Funktionen verwendet, während die mehrzeilige Fehlerausgabe weniger fehleranfällig ist (da Sie nicht unbedingt jede Zeile mit &>2
versehen müssen).