La risposta di Glenn è buona: la distinzione tra ( ... )
ed { ... }
è importante.
Una strategia che uso spesso per l'output di errori come quello che è nella tua domanda è il tee
comando. Potresti fare qualcosa del genere:
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"
Il tee
comando invierà l'output in due posizioni; -a
l'opzione "aggiunge" l'output al file indicato e il comando passerà anche l'input a stdout. Il >&2
alla fine della riga reindirizza lo tee
stdout a stderr, che può essere gestito in modo diverso (cioè in un lavoro cron).
Un altro suggerimento che utilizzo spesso negli script di shell è quello di modificare il comportamento del debug o dell'output dettagliato in base al fatto che lo script sia in esecuzione su un terminale o abbia -v
un'opzione fornita. Per esempio:
#!/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
Gli script possono iniziare con qualcosa di generico come questo nella parte superiore, con l'output di Verbose e Debug sparsi in tutto lo script. È solo un modo per farlo: ce ne sono molti e persone diverse avranno il loro modo di gestire queste cose, specialmente se sono in giro da un po '. :)
Un'altra opzione è gestire l'output con un "gestore", una funzione shell che può fare cose più intelligenti. Per esempio:
#!/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"
(Nota che ${var^^}
è solo bash.)
Questo crea una funzione shell che può usare le syslog
funzioni del tuo sistema (con logger
comando ) to send things to system logs. The
logme () `La funzione può essere usata sia con opzioni che generano singole linee di dati di registro, sia con più linee di input che vengono elaborate su stdin. sembra allettante.
Nota che questo è un esempio e probabilmente non dovrebbe essere copiato alla lettera se non lo capisci e sai che fa esattamente quello che ti serve. Un'idea migliore è prendere qui i concetti e implementarli da soli nei propri script.