La respuesta de Glenn es buena: la distinción entre ( ... )
y { ... }
es importante.
Una estrategia que uso a menudo para la salida de errores, como lo que hay en su pregunta, es el tee
comando. Podrías hacer algo como esto:
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"
El tee
comando enviará la salida a dos lugares; -a
la opción "agrega" salida al archivo nombrado, y el comando también pasará la entrada a stdout. El >&2
final de la línea redirige tee
el stdout de stdout a stderr, que puede manejarse de manera diferente (es decir, en un trabajo cron).
Otro consejo que uso a menudo en los scripts de shell es cambiar el comportamiento de la depuración o la salida detallada en función de si el script se ejecuta en un terminal o tiene una -v
opción provista. Por ejemplo:
#!/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
Las secuencias de comandos pueden comenzar con algo genérico como este en la parte superior, con resultados detallados y de depuración esparcidos por toda la secuencia de comandos. Es solo una forma de hacerlo: hay muchas, y diferentes personas tendrán su propia manera de manejar estas cosas, especialmente si han estado alrededor por un tiempo. :)
Una opción más es manejar su salida con un "controlador", una función de shell que puede hacer cosas más inteligentes. Por ejemplo:
#!/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"
(Tenga en cuenta que solo ${var^^}
es bash).
Esto crea una función de shell que puede usar las syslog
funciones de su sistema (con la función de logger
comando ) to send things to system logs. The
logme () `puede usarse con opciones que generan líneas individuales de datos de registro o con múltiples líneas de entrada que se procesan en stdin. Juegue con ella si Parece atractivo
Tenga en cuenta que este es un ejemplo y probablemente no debería copiarse literalmente a menos que lo entienda y sepa que hace exactamente lo que necesita. Una mejor idea es tomar los conceptos aquí e implementarlos usted mismo en sus propios scripts.