Glenns Antwort ist gut - die Unterscheidung zwischen ( ... )
und { ... }
ist wichtig.
Eine Strategie, die ich häufig für die Fehlerausgabe verwende, wie z. B. Ihre Frage, ist der tee
Befehl. Sie könnten so etwas tun:
echo "Normal output"
{
printf "[%s] %s\n" "$(date '+%Y-%m-%d %T')" "Warning text"
printf "[%s] %s\n" "$(date '+%Y-%m-%d %T')" "This event is logged."
} | tee -a $logfile >&2
echo "More normal output"
Der tee
Befehl sendet die Ausgabe an zwei Stellen. -a
Die Option "hängt" die Ausgabe an die benannte Datei an, und der Befehl leitet die Eingabe auch an stdout weiter. Das >&2
am Ende der Zeile stehende tee
stdout leitet es an stderr weiter, was möglicherweise anders gehandhabt wird (dh in einem Cron-Job).
Ein weiterer Tipp, den ich häufig in Shell-Skripten verwende, besteht darin, das Verhalten der Debug- oder ausführlichen Ausgabe zu ändern, je nachdem, ob das Skript auf einem Terminal ausgeführt wird oder über eine -v
Option verfügt. Zum Beispiel:
#!/bin/sh
# Set defaults
if [ -t 0 ]; then
Verbose=true; vflag="-v"
else
Verbose=false; vflag=""
fi
Debug=false; AskYN=true; Doit=true
# Detect options (altering defaults)
while getopts vdqbn opt; do
case "$opt" in
v) Verbose=true; vflag="-v" ;; # Verbose mode
d) Debug=true; Verbose=true; vflag="-v" ;; # Very Verbose
q) Verbose=false; vflag="" ;; # quiet mode (non-verbose)
b) AskYN=false ;; # batch mode
n) Doit=false ;; # test mode
*) usage; exit 1 ;;
esac
done
# Shift our options for further processing
shift $(($OPTIND - 1))
$Verbose && echo "INFO: Verbose output is turned on." >&2
$Debug && echo "INFO: In fact, expect to be overrun." >&2
# Do your thing here
if $AskYN; then
read -p "Continue? " choice
case "$choice" in
Y|y) $Doit && somecommand ;;
*) echo "Done." ;;
esac
fi
Skripte können mit etwas Allgemeinem wie diesem oben beginnen, wobei die Ausgabe von Verbose und Debug im gesamten Skript verteilt ist. Es ist nur eine Möglichkeit, dies zu tun - es gibt viele, und verschiedene Leute werden alle ihre eigene Art haben, mit diesen Dingen umzugehen, besonders wenn sie schon eine Weile da sind. :) :)
Eine weitere Option besteht darin, Ihre Ausgabe mit einem "Handler" zu verarbeiten - einer Shell-Funktion, die möglicherweise intelligentere Aufgaben ausführt. Zum Beispiel:
#!/bin/bash
logme() {
case "${1^^}" in
[IN]*) level=notice ;;
W*) level=warning ;;
A*) level=alert ;;
E*) level=emerg ;;
*) level=notice ;;
esac
if [[ "$#" -eq 1 ]]; then
# Strip off unnecessary prefixes like "INFO:"
string="${1#+([A-Z])?(:) }"
else
shift
string="$@"
fi
logger -p "${facility}.${level}" -t "$(hostname -s)" "$string"
}
echo "Normal output"
logme INFO "Here we go..."
somecommand | logme
echo "Additional normal output"
(Beachten Sie, dass dies ${var^^}
nur Bash ist.)
Dadurch wird eine Shell-Funktion erstellt, die möglicherweise die syslog
Funktionen Ihres Systems verwendet (mit dem logger
Befehl ) to send things to system logs. The
logme (). Die Funktion kann entweder mit Optionen verwendet werden, die einzelne Zeilen von Protokolldaten generieren, oder mit mehreren Eingabezeilen, die auf stdin verarbeitet werden. Spielen Sie damit, wenn dies der Fall ist scheint ansprechend.
Beachten Sie, dass dies ein Beispiel ist und wahrscheinlich nicht wörtlich kopiert werden sollte, es sei denn, Sie verstehen es und wissen, dass es genau das tut, was Sie brauchen. Eine bessere Idee ist es, die Konzepte hier zu übernehmen und sie selbst in Ihren eigenen Skripten zu implementieren.