A resposta de Glenn é boa - a distinção entre ( ... )e { ... }é importante.
Uma estratégia que costumo usar para gerar erros como o que está em sua pergunta é o teecomando. 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 teecomando enviará a saída para dois lugares; -aA opção "anexa" a saída ao arquivo nomeado, e o comando também passará a entrada para o stdout. O >&2no final da linha redireciona teeo stdout do stderr, que pode ser tratado de maneira diferente (ou seja, em um trabalho cron).
Uma outra dica que costumo usar em scripts de shell é alterar o comportamento da depuração ou saída detalhada, com base no fato de o script estar sendo executado em um terminal ou ter uma -vopção 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 esse no topo, com a saída Verbose e Debug espalhadas por todo o script. É apenas uma maneira de fazer isso - existem muitos, e pessoas diferentes terão seu próprio jeito de lidar com essas coisas, especialmente se elas já existem 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^^}é apenas para o bash.)
Isso cria uma função shell que pode usar as syslogfunções do seu sistema (com o loggercomando ) to send things to system logs. Thelogme () `, a função pode ser usada com opções que geram linhas únicas de dados de log ou com várias linhas de entrada que são processadas no stdin. parece atraente.
Observe que este é um exemplo e provavelmente não deve ser copiado literalmente, a menos que você o entenda e saiba que ele faz exatamente o que você precisa. Uma idéia melhor é pegar os conceitos aqui e implementá-los em seus próprios scripts.