A resposta de Glenn é boa - a distinção entre ( ... )
e { ... }
é importante.
Uma estratégia que eu geralmente uso para a saída de erros, como o que está em sua pergunta, é o comando tee
. Você poderia fazer algo assim:
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"
O comando tee
enviará a saída para dois locais; -a
opção "anexa" a saída ao arquivo nomeado e o comando também passará a entrada ao stdout. O >&2
no final da linha redireciona a stdout de tee
para stderr, que pode ser tratada de maneira diferente (ou seja, em uma tarefa cron).
Uma outra dica que costumo usar em scripts de shell é alterar o comportamento da saída de depuração ou detalhada com base no fato de o script estar sendo executado em um terminal ou ter uma opção -v
fornecida. Por exemplo:
#!/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
Os scripts podem começar com algo genérico como este na parte superior, com a saída Detalhada e Depuração espalhada por todo o script. É apenas uma maneira de fazer isso - há muitos, e pessoas diferentes terão seu próprio jeito de lidar com essas coisas, especialmente se já estiverem por aí há algum tempo. :)
Mais uma opção é manipular sua saída com um "manipulador" - uma função de shell que pode fazer coisas mais inteligentes. Por exemplo:
#!/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"
(Observe que ${var^^}
é somente bash.)
Isso cria uma função de shell que pode usar a função syslog
funções do seu sistema (com logger
comando ) to send things to system logs. The
logme () 'pode ser usada com opções que geram linhas únicas de dados de log ou com várias linhas de entrada que é processada em stdin. Jogue com ela se parecer atraente.
Note que este é um exemplo e provavelmente não deve ser copiado textualmente a menos que você o entenda e saiba que ele faz exatamente o que você precisa. Uma ideia melhor é pegar os conceitos aqui e implementá-los em seus próprios scripts.