La réponse de Glenn est bonne - la distinction entre ( ... )
et { ... }
est importante.
Une stratégie que j'utilise souvent pour la sortie d'erreur comme ce qui est dans votre question est la tee
commande. Vous pourriez faire quelque chose comme ça:
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"
La tee
commande enverra la sortie à deux endroits; -a
l'option "ajoute" la sortie au fichier nommé, et la commande passera également l'entrée à stdout. La >&2
fin de la ligne redirige la sortie tee
standard de stdout vers stderr, qui peut être traitée différemment (c'est-à-dire dans une tâche cron).
Une autre astuce que j'utilise souvent dans les scripts shell est de changer le comportement du débogage ou de la sortie détaillée selon que le script s'exécute sur un terminal ou dispose d'une -v
option. Par exemple:
#!/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
Les scripts peuvent commencer par quelque chose de générique comme celui-ci en haut, avec des sorties verbeuses et de débogage dispersées tout au long du script. C'est juste une façon de le faire - il y en a beaucoup, et différentes personnes auront toutes leur propre façon de gérer ce genre de choses, surtout si elles existent depuis un certain temps. :)
Une autre option consiste à gérer votre sortie avec un "gestionnaire" - une fonction shell qui peut faire des choses plus intelligentes. Par exemple:
#!/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"
(Notez que ${var^^}
c'est uniquement bash.)
Cela crée une fonction shell qui peut utiliser les syslog
fonctions de votre système (avec la logger
commande ) to send things to system logs. The
logme () `la fonction peut être utilisée soit avec des options qui génèrent des lignes de données de journal uniques, soit avec plusieurs lignes d'entrée qui sont traitées sur stdin. Jouez avec si elle semble attrayant.
Notez que ceci est un exemple et ne devrait probablement pas être copié mot pour mot à moins que vous ne le compreniez et sachiez qu'il fait exactement ce dont vous avez besoin. Une meilleure idée est de prendre les concepts ici et de les implémenter vous-même dans vos propres scripts.